1 /* DFP.C (c) Copyright Roger Bowler, 2007-2009 */
2 /* Decimal Floating Point instructions */
3
4 /*-------------------------------------------------------------------*/
5 /* This module implements the Decimal Floating Point instructions */
6 /* and the Floating Point Support Enhancement Facility instructions */
7 /* described in the z/Architecture Principles of Operation manual. */
8 /*-------------------------------------------------------------------*/
9
10 #include "hstdinc.h"
11
12 #if !defined(_HENGINE_DLL_)
13 #define _HENGINE_DLL_
14 #endif
15
16 #if !defined(_DFP_C_)
17 #define _DFP_C_
18 #endif
19
20 #include "hercules.h"
21 #include "opcode.h"
22 #include "inline.h"
23
24 #if defined(FEATURE_DECIMAL_FLOATING_POINT)
25 #include "decimal128.h"
26 #include "decimal64.h"
27 #include "decimal32.h"
28 #include "decPacked.h"
29 #endif /*defined(FEATURE_DECIMAL_FLOATING_POINT)*/
30
31 #if defined(FEATURE_FPS_ENHANCEMENT)
32 /*===================================================================*/
33 /* FLOATING POINT SUPPORT INSTRUCTIONS */
34 /*===================================================================*/
35 /* Note: the Floating Point Support instructions use the HFPREG_CHECK
36 and HFPREG2_CHECK macros to enforce an AFP-register data exception
37 if an FPS instruction attempts to use one of the 12 additional FPR
38 registers when the AFP-register-control bit in CR0 is zero. */
39
40 /*-------------------------------------------------------------------*/
41 /* B370 LPDFR - Load Positive FPR Long Register [RRE] */
42 /*-------------------------------------------------------------------*/
DEF_INST(load_positive_fpr_long_reg)43 DEF_INST(load_positive_fpr_long_reg)
44 {
45 int r1, r2; /* Values of R fields */
46 int i1, i2; /* FP register subscripts */
47
48 RRE(inst, regs, r1, r2);
49 HFPREG2_CHECK(r1, r2, regs);
50 i1 = FPR2I(r1);
51 i2 = FPR2I(r2);
52
53 /* Copy register contents, clear the sign bit */
54 regs->fpr[i1] = regs->fpr[i2] & 0x7FFFFFFF;
55 regs->fpr[i1+1] = regs->fpr[i2+1];
56
57 } /* end DEF_INST(load_positive_fpr_long_reg) */
58
59
60 /*-------------------------------------------------------------------*/
61 /* B371 LNDFR - Load Negative FPR Long Register [RRE] */
62 /*-------------------------------------------------------------------*/
DEF_INST(load_negative_fpr_long_reg)63 DEF_INST(load_negative_fpr_long_reg)
64 {
65 int r1, r2; /* Values of R fields */
66 int i1, i2; /* FP register subscripts */
67
68 RRE(inst, regs, r1, r2);
69 HFPREG2_CHECK(r1, r2, regs);
70 i1 = FPR2I(r1);
71 i2 = FPR2I(r2);
72
73 /* Copy register contents, set the sign bit */
74 regs->fpr[i1] = regs->fpr[i2] | 0x80000000;
75 regs->fpr[i1+1] = regs->fpr[i2+1];
76
77 } /* end DEF_INST(load_negative_fpr_long_reg) */
78
79
80 /*-------------------------------------------------------------------*/
81 /* B372 CPSDR - Copy Sign FPR Long Register [RRF] */
82 /*-------------------------------------------------------------------*/
DEF_INST(copy_sign_fpr_long_reg)83 DEF_INST(copy_sign_fpr_long_reg)
84 {
85 int r1, r2, r3; /* Values of R fields */
86 int i1, i2, i3; /* FP register subscripts */
87 U32 sign; /* Work area for sign bit */
88
89 RRF_M(inst, regs, r1, r2, r3);
90 HFPREG2_CHECK(r1, r2, regs);
91 HFPREG_CHECK(r3, regs);
92 i1 = FPR2I(r1);
93 i2 = FPR2I(r2);
94 i3 = FPR2I(r3);
95
96 /* Copy the sign bit from r3 register */
97 sign = regs->fpr[i3] & 0x80000000;
98
99 /* Copy r2 register contents to r1 register */
100 regs->fpr[i1] = regs->fpr[i2];
101 regs->fpr[i1+1] = regs->fpr[i2+1];
102
103 /* Insert the sign bit into r1 register */
104 regs->fpr[i1] &= 0x7FFFFFFF;
105 regs->fpr[i1] |= sign;
106
107 } /* end DEF_INST(copy_sign_fpr_long_reg) */
108
109
110 /*-------------------------------------------------------------------*/
111 /* B373 LCDFR - Load Complement FPR Long Register [RRE] */
112 /*-------------------------------------------------------------------*/
DEF_INST(load_complement_fpr_long_reg)113 DEF_INST(load_complement_fpr_long_reg)
114 {
115 int r1, r2; /* Values of R fields */
116 int i1, i2; /* FP register subscripts */
117
118 RRE(inst, regs, r1, r2);
119 HFPREG2_CHECK(r1, r2, regs);
120 i1 = FPR2I(r1);
121 i2 = FPR2I(r2);
122
123 /* Copy register contents, invert sign bit */
124 regs->fpr[i1] = regs->fpr[i2] ^ 0x80000000;
125 regs->fpr[i1+1] = regs->fpr[i2+1];
126
127 } /* end DEF_INST(load_complement_fpr_long_reg) */
128
129
130 /*-------------------------------------------------------------------*/
131 /* B3C1 LDGR - Load FPR from GR Long Register [RRE] */
132 /*-------------------------------------------------------------------*/
DEF_INST(load_fpr_from_gr_long_reg)133 DEF_INST(load_fpr_from_gr_long_reg)
134 {
135 int r1, r2; /* Values of R fields */
136 int i1; /* FP register subscript */
137
138 RRE(inst, regs, r1, r2);
139 HFPREG_CHECK(r1, regs);
140 i1 = FPR2I(r1);
141
142 /* Load FP register contents from general register */
143 regs->fpr[i1] = regs->GR_H(r2);
144 regs->fpr[i1+1] = regs->GR_L(r2);
145
146 } /* end DEF_INST(load_fpr_from_gr_long_reg) */
147
148
149 /*-------------------------------------------------------------------*/
150 /* B3CD LGDR - Load GR from FPR Long Register [RRE] */
151 /*-------------------------------------------------------------------*/
DEF_INST(load_gr_from_fpr_long_reg)152 DEF_INST(load_gr_from_fpr_long_reg)
153 {
154 int r1, r2; /* Values of R fields */
155 int i2; /* FP register subscript */
156
157 RRE(inst, regs, r1, r2);
158 HFPREG_CHECK(r2, regs);
159 i2 = FPR2I(r2);
160
161 /* Load general register contents from FP register */
162 regs->GR_H(r1) = regs->fpr[i2];
163 regs->GR_L(r1) = regs->fpr[i2+1];
164
165 } /* end DEF_INST(load_gr_from_fpr_long_reg) */
166
167
168 /*-------------------------------------------------------------------*/
169 /* B2B9 SRNMT - Set DFP Rounding Mode [S] */
170 /*-------------------------------------------------------------------*/
DEF_INST(set_dfp_rounding_mode)171 DEF_INST(set_dfp_rounding_mode)
172 {
173 int b2; /* Base of effective addr */
174 VADR effective_addr2; /* Effective address */
175
176 S(inst, regs, b2, effective_addr2);
177
178 DFPINST_CHECK(regs);
179
180 /* Set DFP rounding mode in FPC register from address bits 61-63 */
181 regs->fpc &= ~(FPC_DRM);
182 regs->fpc |= ((effective_addr2 << FPC_DRM_SHIFT) & FPC_DRM);
183
184 } /* end DEF_INST(set_dfp_rounding_mode) */
185
186
187 #endif /*defined(FEATURE_FPS_ENHANCEMENT)*/
188
189
190 #if defined(FEATURE_IEEE_EXCEPTION_SIMULATION)
191 /*===================================================================*/
192 /* IEEE-EXCEPTION-SIMULATION FACILITY INSTRUCTIONS */
193 /*===================================================================*/
194
195 #if !defined(_IXS_ARCH_INDEPENDENT_)
196 /*-------------------------------------------------------------------*/
197 /* Check if a simulated-IEEE-exception event is to be recognized */
198 /* */
199 /* This subroutine is called by the LFAS and SFASR instructions to */
200 /* determine whether the instruction should raise a data exception */
201 /* at the end of the instruction and, if so, the DXC code to be set. */
202 /* */
203 /* Input: */
204 /* cur_fpc Current value of the FPC register */
205 /* src_fpc Value of instruction source operand */
206 /* Output: */
207 /* The return value is the data exception code (DXC), or */
208 /* zero if no simulated-IEEE-exception event is recognized */
209 /*-------------------------------------------------------------------*/
210 static BYTE
fpc_signal_check(U32 cur_fpc,U32 src_fpc)211 fpc_signal_check(U32 cur_fpc, U32 src_fpc)
212 {
213 U32 ff, sm, enabled_flags; /* Mask and flag work areas */
214 BYTE dxc; /* Data exception code or 0 */
215
216 /* AND the current FPC flags with the source FPC mask */
217 ff = (cur_fpc & FPC_FLAG) >> FPC_FLAG_SHIFT;
218 sm = (src_fpc & FPC_MASK) >> FPC_MASK_SHIFT;
219 enabled_flags = (ff & sm) << FPC_FLAG_SHIFT;
220
221 /* A simulated-IEEE-exception event is recognized
222 if any current flag corresponds to the source mask */
223 if (enabled_flags & FPC_FLAG_SFI)
224 {
225 dxc = DXC_IEEE_INV_OP_IISE;
226 }
227 else if (enabled_flags & FPC_FLAG_SFZ)
228 {
229 dxc = DXC_IEEE_DIV_ZERO_IISE;
230 }
231 else if (enabled_flags & FPC_FLAG_SFO)
232 {
233 dxc = (cur_fpc & FPC_FLAG_SFX) ?
234 DXC_IEEE_OF_INEX_IISE :
235 DXC_IEEE_OF_EXACT_IISE;
236 }
237 else if (enabled_flags & FPC_FLAG_SFU)
238 {
239 dxc = (cur_fpc & FPC_FLAG_SFX) ?
240 DXC_IEEE_UF_INEX_IISE :
241 DXC_IEEE_UF_EXACT_IISE;
242 }
243 else if (enabled_flags & FPC_FLAG_SFX)
244 {
245 dxc = DXC_IEEE_INEXACT_IISE;
246 }
247 else
248 {
249 dxc = 0;
250 }
251
252 /* Return data exception code or zero */
253 return dxc;
254 } /* end function fpc_signal_check */
255 #define _IXS_ARCH_INDEPENDENT_
256 #endif /*!defined(_IXS_ARCH_INDEPENDENT_)*/
257
258
259 /*-------------------------------------------------------------------*/
260 /* B2BD LFAS - Load FPC and Signal [S] */
261 /*-------------------------------------------------------------------*/
DEF_INST(load_fpc_and_signal)262 DEF_INST(load_fpc_and_signal)
263 {
264 int b2; /* Base of effective addr */
265 VADR effective_addr2; /* Effective address */
266 U32 src_fpc, new_fpc; /* New value for FPC */
267 BYTE dxc; /* Data exception code */
268
269 S(inst, regs, b2, effective_addr2);
270
271 DFPINST_CHECK(regs);
272
273 /* Load new FPC register contents from operand location */
274 src_fpc = ARCH_DEP(vfetch4) (effective_addr2, b2, regs);
275
276 /* Program check if reserved bits are non-zero */
277 FPC_CHECK(src_fpc, regs);
278
279 /* OR the flags from the current FPC register */
280 new_fpc = src_fpc | (regs->fpc & FPC_FLAG);
281
282 /* Determine whether an event is to be signaled */
283 dxc = fpc_signal_check(regs->fpc, src_fpc);
284
285 /* Update the FPC register */
286 regs->fpc = new_fpc;
287
288 /* Signal a simulated-IEEE-exception event if needed */
289 if (dxc != 0)
290 {
291 regs->dxc = dxc;
292 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
293 }
294
295 } /* end DEF_INST(load_fpc_and_signal) */
296
297
298 /*-------------------------------------------------------------------*/
299 /* B385 SFASR - Set FPC and Signal [RRE] */
300 /*-------------------------------------------------------------------*/
DEF_INST(set_fpc_and_signal)301 DEF_INST(set_fpc_and_signal)
302 {
303 int r1, unused; /* Values of R fields */
304 U32 src_fpc, new_fpc; /* New value for FPC */
305 BYTE dxc; /* Data exception code */
306
307 RRE(inst, regs, r1, unused);
308
309 DFPINST_CHECK(regs);
310
311 /* Load new FPC register contents from R1 register bits 32-63 */
312 src_fpc = regs->GR_L(r1);
313
314 /* Program check if reserved bits are non-zero */
315 FPC_CHECK(src_fpc, regs);
316
317 /* OR the flags from the current FPC register */
318 new_fpc = src_fpc | (regs->fpc & FPC_FLAG);
319
320 /* Determine whether an event is to be signaled */
321 dxc = fpc_signal_check(regs->fpc, src_fpc);
322
323 /* Update the FPC register */
324 regs->fpc = new_fpc;
325
326 /* Signal a simulated-IEEE-exception event if needed */
327 if (dxc != 0)
328 {
329 regs->dxc = dxc;
330 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
331 }
332
333 } /* end DEF_INST(set_fpc_and_signal) */
334 #endif /*defined(FEATURE_IEEE_EXCEPTION_SIMULATION)*/
335
336
337 #if defined(FEATURE_DECIMAL_FLOATING_POINT)
338 /*===================================================================*/
339 /* DECIMAL FLOATING POINT INSTRUCTIONS */
340 /*===================================================================*/
341 /* Note: the DFP instructions use the DFPINST_CHECK macro to check the
342 setting of the AFP-register-control bit in CR0. If this bit is zero
343 then the macro generates a DFP-instruction data exception. */
344
345 #if !defined(_DFP_ARCH_INDEPENDENT_)
346 /*-------------------------------------------------------------------*/
347 /* Extract the leftmost digit from a decimal32/64/128 structure */
348 /*-------------------------------------------------------------------*/
349 static const int
350 dfp_lmdtable[32] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
351 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, 0, 0};
352
353 static inline int
dfp32_extract_lmd(decimal32 * xp)354 dfp32_extract_lmd(decimal32 *xp)
355 {
356 unsigned int cf = (((FW*)xp)->F & 0x7C000000) >> 26;
357 return dfp_lmdtable[cf];
358 } /* end function dfp32_extract_lmd */
359
360 static inline int
dfp64_extract_lmd(decimal64 * xp)361 dfp64_extract_lmd(decimal64 *xp)
362 {
363 unsigned int cf = (((DW*)xp)->F.H.F & 0x7C000000) >> 26;
364 return dfp_lmdtable[cf];
365 } /* end function dfp64_extract_lmd */
366
367 static inline int
dfp128_extract_lmd(decimal128 * xp)368 dfp128_extract_lmd(decimal128 *xp)
369 {
370 unsigned int cf = (((QW*)xp)->F.HH.F & 0x7C000000) >> 26;
371 return dfp_lmdtable[cf];
372 } /* end function dfp128_extract_lmd */
373
374 /*-------------------------------------------------------------------*/
375 /* Clear the CF and BXCF fields of a decimal32/64/128 structure */
376 /*-------------------------------------------------------------------*/
377 static inline void
dfp32_clear_cf_and_bxcf(decimal32 * xp)378 dfp32_clear_cf_and_bxcf(decimal32 *xp)
379 {
380 ((FW*)xp)->F &= 0x800FFFFF; /* Clear CF and BXCF fields */
381 } /* end function dfp32_clear_cf_and_bxcf */
382
383 static inline void
dfp64_clear_cf_and_bxcf(decimal64 * xp)384 dfp64_clear_cf_and_bxcf(decimal64 *xp)
385 {
386 ((DW*)xp)->F.H.F &= 0x8003FFFF; /* Clear CF and BXCF fields */
387 } /* end function dfp64_clear_cf_and_bxcf */
388
389 static inline void
dfp128_clear_cf_and_bxcf(decimal128 * xp)390 dfp128_clear_cf_and_bxcf(decimal128 *xp)
391 {
392 ((QW*)xp)->F.HH.F &= 0x80003FFF; /* Clear CF and BXCF fields */
393 } /* end function dfp128_clear_cf_and_bxcf */
394
395 /*-------------------------------------------------------------------*/
396 /* Set the CF and BXCF fields of a decimal32/64/128 structure */
397 /* Input: */
398 /* xp Pointer to a decimal32/64/128 structure */
399 /* cfs A 32-bit value, of which bits 0-25 are ignored, */
400 /* bits 26-30 contain the new CF field value (5-bits), */
401 /* bit 31 is the new BXCF signaling indicator (1-bit). */
402 /* Output: */
403 /* The CF field and the high-order bit of the BXCF field in */
404 /* the decimal32/64/128 structure are set to the indicated */
405 /* values and the remaining bits of the BXCF field are cleared. */
406 /*-------------------------------------------------------------------*/
407 #define DFP_CFS_INF ((30<<1)|0) /* CF and BXCF-S for Inf */
408 #define DFP_CFS_QNAN ((31<<1)|0) /* CF and BXCF-S for QNaN */
409 #define DFP_CFS_SNAN ((31<<1)|1) /* CF and BXCF-S for SNaN */
410
411 static inline void
dfp32_set_cf_and_bxcf(decimal32 * xp,U32 cfs)412 dfp32_set_cf_and_bxcf(decimal32 *xp, U32 cfs)
413 {
414 ((FW*)xp)->F &= 0x800FFFFF; /* Clear CF and BXCF fields */
415 ((FW*)xp)->F |= (cfs & 0x3F) << 25;
416 /* Set CF and BXCF S-bit */
417 } /* end function dfp32_set_cf_and_bxcf */
418
419 static inline void
dfp64_set_cf_and_bxcf(decimal64 * xp,U32 cfs)420 dfp64_set_cf_and_bxcf(decimal64 *xp, U32 cfs)
421 {
422 ((DW*)xp)->F.H.F &= 0x8003FFFF; /* Clear CF and BXCF fields */
423 ((DW*)xp)->F.H.F |= (cfs & 0x3F) << 25;
424 /* Set CF and BXCF S-bit */
425 } /* end function dfp64_set_cf_and_bxcf */
426
427 static inline void
dfp128_set_cf_and_bxcf(decimal128 * xp,U32 cfs)428 dfp128_set_cf_and_bxcf(decimal128 *xp, U32 cfs)
429 {
430 ((QW*)xp)->F.HH.F &= 0x80003FFF; /* Clear CF and BXCF fields */
431 ((QW*)xp)->F.HH.F |= (cfs & 0x3F) << 25;
432 /* Set CF and BXCF S-bit */
433 } /* end function dfp128_set_cf_and_bxcf */
434
435 /*-------------------------------------------------------------------*/
436 /* Compare exponent and return condition code */
437 /* */
438 /* This subroutine is called by the CEETR, CEDTR, and CEXTR */
439 /* instructions. It compares the exponents of two decimal */
440 /* numbers and returns a condition code. */
441 /* */
442 /* Input: */
443 /* d1,d2 Pointers to decimal number structures */
444 /* Output: */
445 /* The return value is the condition code */
446 /*-------------------------------------------------------------------*/
447 static inline int
dfp_compare_exponent(decNumber * d1,decNumber * d2)448 dfp_compare_exponent(decNumber *d1, decNumber *d2)
449 {
450 int cc; /* Condition code */
451
452 if (decNumberIsNaN(d1) && decNumberIsNaN(d2))
453 cc = 0;
454 else if (decNumberIsNaN(d1) || decNumberIsNaN(d2))
455 cc = 3;
456 else if (decNumberIsInfinite(d1) && decNumberIsInfinite(d2))
457 cc = 0;
458 else if (decNumberIsInfinite(d1) || decNumberIsInfinite(d2))
459 cc = 3;
460 else
461 cc = (d1->exponent == d2->exponent) ? 0 :
462 (d1->exponent < d2->exponent) ? 1 : 2 ;
463
464 return cc;
465 } /* end function dfp_compare_exponent */
466
467 /*-------------------------------------------------------------------*/
468 /* Convert 64-bit signed binary integer to decimal number */
469 /* */
470 /* This subroutine is called by the CDGTR and CXGTR instructions. */
471 /* It converts a 64-bit signed binary integer value into a */
472 /* decimal number structure. The inexact condition will be set */
473 /* in the decimal context structure if the number is rounded to */
474 /* fit the maximum number of digits specified in the context. */
475 /* */
476 /* Input: */
477 /* dn Pointer to decimal number structure */
478 /* n 64-bit signed binary integer value */
479 /* pset Pointer to decimal number context structure */
480 /* Output: */
481 /* The decimal number structure is updated. */
482 /*-------------------------------------------------------------------*/
483 static void
dfp_number_from_fix64(decNumber * dn,S64 n,decContext * pset)484 dfp_number_from_fix64(decNumber *dn, S64 n, decContext *pset)
485 {
486 int sign = 0; /* Sign of binary integer */
487 int i; /* Counter */
488 char zoned[32]; /* Zoned decimal work area */
489 static char maxnegzd[]="-9223372036854775808";
490 static U64 maxneg64 = 0x8000000000000000ULL;
491
492 /* Handle maximum negative number as special case */
493 if (n == (S64)maxneg64)
494 {
495 decNumberFromString(dn, maxnegzd, pset);
496 return;
497 }
498
499 /* Convert binary value to zoned decimal */
500 if (n < 0) { n = -n; sign = 1; }
501 i = sizeof(zoned) - 1;
502 zoned[i] = '\0';
503 do {
504 zoned[--i] = (n % 10) + '0';
505 n /= 10;
506 } while(i > 1 && n > 0);
507 if (sign) zoned[--i] = '-';
508
509 /* Convert zoned decimal value to decimal number structure */
510 decNumberFromString(dn, zoned+i, pset);
511
512 } /* end function dfp_number_from_fix64 */
513
514 /*-------------------------------------------------------------------*/
515 /* Convert decimal number to 64-bit signed binary integer */
516 /* */
517 /* This subroutine is called by the CGDTR and CGXTR instructions. */
518 /* It converts a decimal number structure to a 64-bit signed */
519 /* binary integer value. The inexact condition will be set in */
520 /* the decimal context structure if the number is rounded to */
521 /* an integer. The invalid operation condition will be set if */
522 /* the decimal value is outside the range of a 64-bit integer. */
523 /* */
524 /* Input: */
525 /* b Pointer to decimal number structure */
526 /* pset Pointer to decimal number context structure */
527 /* Output: */
528 /* The return value is the 64-bit signed binary integer result */
529 /*-------------------------------------------------------------------*/
530 static S64
dfp_number_to_fix64(decNumber * b,decContext * pset)531 dfp_number_to_fix64(decNumber *b, decContext *pset)
532 {
533 S64 n; /* 64-bit signed result */
534 int32_t scale; /* Scaling factor */
535 unsigned i; /* Array subscript */
536 BYTE packed[17]; /* 33-digit packed work area */
537 decNumber p, c; /* Working decimal numbers */
538 static U64 mp64 = 0x7FFFFFFFFFFFFFFFULL; /* Max pos fixed 64 */
539 static U64 mn64 = 0x8000000000000000ULL; /* Max neg fixed 64 */
540 static char mpzd[]="9223372036854775807"; /* Max pos zoned dec */
541 static char mnzd[]="-9223372036854775808"; /* Max neg zoned dec */
542 static BYTE mpflag = 0; /* 1=mp,mn are initialized */
543 static decNumber mp, mn; /* Decimal maximum pos,neg */
544 decContext setmax; /* Working context for mp,mn */
545
546 /* Prime the decimal number structures representing the maximum
547 positive and negative numbers representable in 64 bits. Use
548 a 128-bit DFP working context because these numbers are too
549 big to be represented in the 32-bit and 64-bit DFP formats */
550 if (mpflag == 0)
551 {
552 decContextDefault(&setmax, DEC_INIT_DECIMAL128);
553 decNumberFromString(&mp, mpzd, &setmax);
554 decNumberFromString(&mn, mnzd, &setmax);
555 mpflag = 1;
556 }
557
558 /* If operand is a NaN then set invalid operation
559 and return maximum negative result */
560 if (decNumberIsNaN(b))
561 {
562 pset->status |= DEC_IEEE_854_Invalid_operation;
563 return (S64)mn64;
564 }
565
566 /* Remove fractional part of decimal number */
567 decNumberToIntegralValue(&p, b, pset);
568
569 /* Special case if operand is less than maximum negative
570 number (including where operand is negative infinity) */
571 decNumberCompare(&c, b, &mn, pset);
572 if (decNumberIsNegative(&c))
573 {
574 /* If rounded value is less than maximum negative number
575 then set invalid operation otherwise set inexact */
576 decNumberCompare(&c, &p, &mn, pset);
577 if (decNumberIsNegative(&c))
578 pset->status |= DEC_IEEE_854_Invalid_operation;
579 else
580 pset->status |= DEC_IEEE_854_Inexact;
581
582 /* Return maximum negative result */
583 return (S64)mn64;
584 }
585
586 /* Special case if operand is greater than maximum positive
587 number (including where operand is positive infinity) */
588 decNumberCompare(&c, b, &mp, pset);
589 if (decNumberIsNegative(&c) == 0 && decNumberIsZero(&c) == 0)
590 {
591 /* If rounded value is greater than maximum positive number
592 then set invalid operation otherwise set inexact */
593 decNumberCompare(&c, &p, &mp, pset);
594 if (decNumberIsNegative(&c) == 0 && decNumberIsZero(&c) == 0)
595 pset->status |= DEC_IEEE_854_Invalid_operation;
596 else
597 pset->status |= DEC_IEEE_854_Inexact;
598
599 /* Return maximum positive result */
600 return (S64)mp64;
601 }
602
603 /* Raise inexact condition if result was rounded */
604 decNumberCompare(&c, &p, b, pset);
605 if (decNumberIsZero(&c) == 0)
606 {
607 pset->status |= DEC_IEEE_854_Inexact;
608 if (decNumberIsNegative(&c) == decNumberIsNegative(b))
609 pset->status |= DEC_Rounded;
610 }
611
612 /* Convert decimal number structure to packed decimal */
613 decPackedFromNumber(packed, sizeof(packed), &scale, &p);
614
615 /* Convert packed decimal to binary value */
616 for (i = 0, n = 0; i < sizeof(packed)-1; i++)
617 {
618 n = n * 10 + ((packed[i] & 0xF0) >> 4);
619 n = n * 10 + (packed[i] & 0x0F);
620 }
621 n = n * 10 + ((packed[i] & 0xF0) >> 4);
622 while (scale++) n *= 10;
623 if ((packed[i] & 0x0F) == 0x0D) n = -n;
624
625 /* Return 64-bit signed result */
626 return n;
627
628 } /* end function dfp_number_to_fix64 */
629
630 #define MAXDECSTRLEN DECIMAL128_String /* Maximum string length */
631 /*-------------------------------------------------------------------*/
632 /* Shift decimal coefficient left or right */
633 /* */
634 /* This subroutine is called by the SLDT, SLXT, SRDT and SRXT */
635 /* instructions. It shifts the coefficient digits of a decimal */
636 /* number left or right. For a left shift, zeroes are appended */
637 /* to the coefficient. For a right shift, digits are dropped */
638 /* from the end of the coefficient. No rounding is performed. */
639 /* The sign and exponent of the number remain unchanged. */
640 /* */
641 /* Input: */
642 /* pset Pointer to decimal number context structure */
643 /* dn Pointer to decimal number structure to be shifted */
644 /* count Number of digits to shift (+ve=left, -ve=right) */
645 /* Output: */
646 /* The decimal number structure is updated. */
647 /*-------------------------------------------------------------------*/
648 static inline void
dfp_shift_coeff(decContext * pset,decNumber * dn,int count)649 dfp_shift_coeff(decContext *pset, decNumber *dn, int count)
650 {
651 int len; /* String length */
652 int maxlen; /* Maximum coefficient length*/
653 int32_t exp; /* Original exponent */
654 uint8_t bits; /* Original flag bits */
655 char zd[MAXDECSTRLEN+64]; /* Zoned decimal work area */
656
657 /* Save original exponent and sign/Inf/NaN bits */
658 exp = dn->exponent;
659 bits = dn->bits;
660
661 /* Clear exponent and sign/Inf/NaN bits */
662 dn->exponent = 0;
663 dn->bits &= ~(DECNEG | DECSPECIAL);
664
665 /* Convert coefficient digits to zoned decimal */
666 decNumberToString(dn, zd);
667 len = (int)strlen(zd);
668
669 /* Shift zoned digits left or right */
670 if (count > 0)
671 memset(zd + len, '0', count);
672 len += count;
673 maxlen = (bits & DECSPECIAL) ? pset->digits - 1 : pset->digits;
674 if (len > maxlen)
675 {
676 memmove(zd, zd + len - maxlen, maxlen);
677 len = maxlen;
678 }
679 else if (len < 1)
680 {
681 zd[0] = '0';
682 len = 1;
683 }
684 zd[len] = '\0';
685
686 /* Convert shifted coefficient to decimal number structure */
687 decNumberFromString(dn, zd, pset);
688
689 /* Restore original exponent and sign/Inf/NaN bits */
690 dn->exponent = exp;
691 dn->bits |= bits & (DECNEG | DECSPECIAL);
692
693 } /* end function dfp_shift_coeff */
694
695 /* Bit numbers for Test Data Class instructions */
696 #define DFP_TDC_ZERO 52
697 #define DFP_TDC_SUBNORMAL 54
698 #define DFP_TDC_NORMAL 56
699 #define DFP_TDC_INFINITY 58
700 #define DFP_TDC_QUIET_NAN 60
701 #define DFP_TDC_SIGNALING_NAN 62
702
703 /*-------------------------------------------------------------------*/
704 /* Test data class and return condition code */
705 /* */
706 /* This subroutine is called by the TDCET, TDCDT, and TDCXT */
707 /* instructions. It tests the data class and sign of a decimal */
708 /* number. Each combination of data class and sign corresponds */
709 /* to one of 12 possible bits in a bitmask. The value (0 or 1) */
710 /* of the corresponding bit is returned. */
711 /* */
712 /* Input: */
713 /* pset Pointer to decimal number context structure */
714 /* dn Pointer to decimal number structure to be tested */
715 /* bits Bitmask in rightmost 12 bits */
716 /* Output: */
717 /* The return value is 0 or 1. */
718 /*-------------------------------------------------------------------*/
719 static inline int
dfp_test_data_class(decContext * pset,decNumber * dn,U32 bits)720 dfp_test_data_class(decContext *pset, decNumber *dn, U32 bits)
721 {
722 int bitn; /* Bit number */
723 decNumber dm; /* Normalized value of dn */
724
725 if (decNumberIsZero(dn))
726 bitn = DFP_TDC_ZERO;
727 else if (decNumberIsInfinite(dn))
728 bitn = DFP_TDC_INFINITY;
729 else if (decNumberIsQNaN(dn))
730 bitn = DFP_TDC_QUIET_NAN;
731 else if (decNumberIsSNaN(dn))
732 bitn = DFP_TDC_SIGNALING_NAN;
733 else {
734 decNumberNormalize(&dm, dn, pset);
735 bitn = (dm.exponent < pset->emin) ?
736 DFP_TDC_SUBNORMAL :
737 DFP_TDC_NORMAL ;
738 }
739
740 if (decNumberIsNegative(dn)) bitn++;
741
742 return (bits >> (63 - bitn)) & 0x01;
743
744 } /* end function dfp_test_data_class */
745
746 /* Bit numbers for Test Data Group instructions */
747 #define DFP_TDG_SAFE_ZERO 52
748 #define DFP_TDG_EXTREME_ZERO 54
749 #define DFP_TDG_EXTREME_NONZERO 56
750 #define DFP_TDG_SAFE_NZ_LMD_Z 58
751 #define DFP_TDG_SAFE_NZ_LMD_NZ 60
752 #define DFP_TDG_SPECIAL 62
753
754 /*-------------------------------------------------------------------*/
755 /* Test data group and return condition code */
756 /* */
757 /* This subroutine is called by the TDGET, TDGDT, and TDGXT */
758 /* instructions. It tests the exponent and leftmost coefficient */
759 /* digit of a decimal number to determine which of 12 possible */
760 /* groups the number corresponds to. Each group corresponds to */
761 /* one of 12 possible bits in a bitmask. The value (0 or 1) of */
762 /* the corresponding bit is returned. */
763 /* */
764 /* Input: */
765 /* pset Pointer to decimal number context structure */
766 /* dn Pointer to decimal number structure to be tested */
767 /* lmd Leftmost digit of decimal FP number */
768 /* bits Bitmask in rightmost 12 bits */
769 /* Output: */
770 /* The return value is 0 or 1. */
771 /*-------------------------------------------------------------------*/
772 static inline int
dfp_test_data_group(decContext * pset,decNumber * dn,int lmd,U32 bits)773 dfp_test_data_group(decContext *pset, decNumber *dn, int lmd, U32 bits)
774 {
775 int bitn; /* Bit number */
776 int extreme; /* 1=exponent is min or max */
777 int exp; /* Adjusted exponent */
778
779 exp = dn->exponent + pset->digits - 1;
780 extreme = (exp == pset->emin) || (exp == pset->emax);
781
782 if (decNumberIsZero(dn))
783 bitn = extreme ?
784 DFP_TDG_EXTREME_ZERO :
785 DFP_TDG_SAFE_ZERO ;
786 else if (decNumberIsInfinite(dn) || decNumberIsNaN(dn))
787 bitn = DFP_TDG_SPECIAL;
788 else if (extreme)
789 bitn = DFP_TDG_EXTREME_NONZERO;
790 else {
791 bitn = (lmd == 0) ?
792 DFP_TDG_SAFE_NZ_LMD_Z :
793 DFP_TDG_SAFE_NZ_LMD_NZ ;
794 }
795
796 if (decNumberIsNegative(dn)) bitn++;
797
798 return (bits >> (63 - bitn)) & 0x01;
799
800 } /* end function dfp_test_data_group */
801
802 #define _DFP_ARCH_INDEPENDENT_
803 #endif /*!defined(_DFP_ARCH_INDEPENDENT_)*/
804
805 #if defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY) /*810*/
806 #if !defined(_DFP_FPE_ARCH_INDEPENDENT_)
807 /*-------------------------------------------------------------------*/
808 /* Convert 32-bit signed binary integer to decimal number */
809 /* */
810 /* This subroutine is called by the CDFTR and CXFTR instructions. */
811 /* It converts a 32-bit signed binary integer value into a */
812 /* decimal number structure. The inexact condition will be set */
813 /* in the decimal context structure if the number is rounded to */
814 /* fit the maximum number of digits specified in the context. */
815 /* */
816 /* Input: */
817 /* dn Pointer to decimal number structure */
818 /* n 32-bit signed binary integer value */
819 /* pset Pointer to decimal number context structure */
820 /* Output: */
821 /* The decimal number structure is updated. */
822 /*-------------------------------------------------------------------*/
823 static void
dfp_number_from_fix32(decNumber * dn,S32 n,decContext * pset)824 dfp_number_from_fix32(decNumber *dn, S32 n, decContext *pset)
825 {
826 int sign = 0; /* Sign of binary integer */
827 int i; /* Counter */
828 char zoned[32]; /* Zoned decimal work area */
829 static char maxnegzd[]="-2147483648";
830 static U32 maxneg32 = 0x80000000UL;
831
832 /* Handle maximum negative number as special case */
833 if (n == (S32)maxneg32)
834 {
835 decNumberFromString(dn, maxnegzd, pset);
836 return;
837 }
838
839 /* Convert binary value to zoned decimal */
840 if (n < 0) { n = -n; sign = 1; }
841 i = sizeof(zoned) - 1;
842 zoned[i] = '\0';
843 do {
844 zoned[--i] = (n % 10) + '0';
845 n /= 10;
846 } while(i > 1 && n > 0);
847 if (sign) zoned[--i] = '-';
848
849 /* Convert zoned decimal value to decimal number structure */
850 decNumberFromString(dn, zoned+i, pset);
851
852 } /* end function dfp_number_from_fix32 */
853
854 /*-------------------------------------------------------------------*/
855 /* Convert 32-bit unsigned binary integer to decimal number */
856 /* */
857 /* This subroutine is called by the CDLFTR and CXLFTR instructions. */
858 /* It converts a 32-bit unsigned binary integer value into a */
859 /* decimal number structure. The inexact condition will be set */
860 /* in the decimal context structure if the number is rounded to */
861 /* fit the maximum number of digits specified in the context. */
862 /* */
863 /* Input: */
864 /* dn Pointer to decimal number structure */
865 /* n 32-bit unsigned binary integer value */
866 /* pset Pointer to decimal number context structure */
867 /* Output: */
868 /* The decimal number structure is updated. */
869 /*-------------------------------------------------------------------*/
870 static void
dfp_number_from_u32(decNumber * dn,U32 n,decContext * pset)871 dfp_number_from_u32(decNumber *dn, U32 n, decContext *pset)
872 {
873 int i; /* Counter */
874 char zoned[32]; /* Zoned decimal work area */
875
876 /* Convert unsigned binary value to zoned decimal */
877 i = sizeof(zoned) - 1;
878 zoned[i] = '\0';
879 do {
880 zoned[--i] = (n % 10) + '0';
881 n /= 10;
882 } while(i > 1 && n > 0);
883
884 /* Convert zoned decimal value to decimal number structure */
885 decNumberFromString(dn, zoned+i, pset);
886
887 } /* end function dfp_number_from_u32 */
888
889 /*-------------------------------------------------------------------*/
890 /* Convert 64-bit unsigned binary integer to decimal number */
891 /* */
892 /* This subroutine is called by the CDLGTR and CXLGTR instructions. */
893 /* It converts a 64-bit unsigned binary integer value into a */
894 /* decimal number structure. The inexact condition will be set */
895 /* in the decimal context structure if the number is rounded to */
896 /* fit the maximum number of digits specified in the context. */
897 /* */
898 /* Input: */
899 /* dn Pointer to decimal number structure */
900 /* n 64-bit unsigned binary integer value */
901 /* pset Pointer to decimal number context structure */
902 /* Output: */
903 /* The decimal number structure is updated. */
904 /*-------------------------------------------------------------------*/
905 static void
dfp_number_from_u64(decNumber * dn,U64 n,decContext * pset)906 dfp_number_from_u64(decNumber *dn, U64 n, decContext *pset)
907 {
908 int i; /* Counter */
909 char zoned[32]; /* Zoned decimal work area */
910
911 /* Convert unsigned binary value to zoned decimal */
912 i = sizeof(zoned) - 1;
913 zoned[i] = '\0';
914 do {
915 zoned[--i] = (n % 10) + '0';
916 n /= 10;
917 } while(i > 1 && n > 0);
918
919 /* Convert zoned decimal value to decimal number structure */
920 decNumberFromString(dn, zoned+i, pset);
921
922 } /* end function dfp_number_from_u64 */
923
924 /*-------------------------------------------------------------------*/
925 /* Convert decimal number to 32-bit signed binary integer */
926 /* */
927 /* This subroutine is called by the CFDTR and CFXTR instructions. */
928 /* It converts a decimal number structure to a 32-bit signed */
929 /* binary integer value. The inexact condition will be set in */
930 /* the decimal context structure if the number is rounded to */
931 /* an integer. The invalid operation condition will be set if */
932 /* the decimal value is outside the range of a 32-bit integer. */
933 /* */
934 /* Input: */
935 /* b Pointer to decimal number structure */
936 /* pset Pointer to decimal number context structure */
937 /* Output: */
938 /* The return value is the 32-bit signed binary integer result */
939 /*-------------------------------------------------------------------*/
940 static S32
dfp_number_to_fix32(decNumber * b,decContext * pset)941 dfp_number_to_fix32(decNumber *b, decContext *pset)
942 {
943 S32 n; /* 32-bit signed result */
944 int32_t scale; /* Scaling factor */
945 unsigned i; /* Array subscript */
946 BYTE packed[17]; /* 33-digit packed work area */
947 decNumber p, c; /* Working decimal numbers */
948 static U32 mp32 = 0x7FFFFFFFUL; /* Max positive fixed 32 */
949 static U32 mn32 = 0x80000000UL; /* Max negative fixed 32 */
950 static char mp32zd[]="2147483647"; /* Max positive zoned dec */
951 static char mn32zd[]="-2147483648"; /* Max negative zoned dec */
952 static BYTE mp32flag = 0; /* 1=mp32dn,mn32dn inited */
953 static decNumber mp32dn, mn32dn; /* Decimal maximum pos,neg */
954 decContext setmax; /* Working context */
955
956 /* Prime the decimal number structures representing the maximum
957 positive and negative numbers representable in 32 bits. Use
958 a 64-bit DFP working context because these numbers are too
959 big to be represented in the 32-bit DFP format */
960 if (mp32flag == 0)
961 {
962 decContextDefault(&setmax, DEC_INIT_DECIMAL64);
963 decNumberFromString(&mp32dn, mp32zd, &setmax);
964 decNumberFromString(&mn32dn, mn32zd, &setmax);
965 mp32flag = 1;
966 }
967
968 /* If operand is a NaN then set invalid operation
969 and return maximum negative result */
970 if (decNumberIsNaN(b))
971 {
972 pset->status |= DEC_IEEE_854_Invalid_operation;
973 return (S32)mn32;
974 }
975
976 /* Remove fractional part of decimal number */
977 decNumberToIntegralValue(&p, b, pset);
978
979 /* Special case if operand is less than maximum negative
980 number (including where operand is negative infinity) */
981 decNumberCompare(&c, b, &mn32dn, pset);
982 if (decNumberIsNegative(&c))
983 {
984 /* If rounded value is less than maximum negative number
985 then set invalid operation otherwise set inexact */
986 decNumberCompare(&c, &p, &mn32dn, pset);
987 if (decNumberIsNegative(&c))
988 pset->status |= DEC_IEEE_854_Invalid_operation;
989 else
990 pset->status |= DEC_IEEE_854_Inexact;
991
992 /* Return maximum negative result */
993 return (S32)mn32;
994 }
995
996 /* Special case if operand is greater than maximum positive
997 number (including where operand is positive infinity) */
998 decNumberCompare(&c, b, &mp32dn, pset);
999 if (decNumberIsNegative(&c) == 0 && decNumberIsZero(&c) == 0)
1000 {
1001 /* If rounded value is greater than maximum positive number
1002 then set invalid operation otherwise set inexact */
1003 decNumberCompare(&c, &p, &mp32dn, pset);
1004 if (decNumberIsNegative(&c) == 0 && decNumberIsZero(&c) == 0)
1005 pset->status |= DEC_IEEE_854_Invalid_operation;
1006 else
1007 pset->status |= DEC_IEEE_854_Inexact;
1008
1009 /* Return maximum positive result */
1010 return (S32)mp32;
1011 }
1012
1013 /* Raise inexact condition if result was rounded */
1014 decNumberCompare(&c, &p, b, pset);
1015 if (decNumberIsZero(&c) == 0)
1016 {
1017 pset->status |= DEC_IEEE_854_Inexact;
1018 if (decNumberIsNegative(&c) == decNumberIsNegative(b))
1019 pset->status |= DEC_Rounded;
1020 }
1021
1022 /* Convert decimal number structure to packed decimal */
1023 decPackedFromNumber(packed, sizeof(packed), &scale, &p);
1024
1025 /* Convert packed decimal to binary value */
1026 for (i = 0, n = 0; i < sizeof(packed)-1; i++)
1027 {
1028 n = n * 10 + ((packed[i] & 0xF0) >> 4);
1029 n = n * 10 + (packed[i] & 0x0F);
1030 }
1031 n = n * 10 + ((packed[i] & 0xF0) >> 4);
1032 while (scale++) n *= 10;
1033 if ((packed[i] & 0x0F) == 0x0D) n = -n;
1034
1035 /* Return 32-bit signed result */
1036 return n;
1037
1038 } /* end function dfp_number_to_fix32 */
1039
1040 /*-------------------------------------------------------------------*/
1041 /* Convert decimal number to 32-bit unsigned binary integer */
1042 /* */
1043 /* This subroutine is called by the CLFDTR and CLFXTR instructions. */
1044 /* It converts a decimal number structure to a 32-bit unsigned */
1045 /* binary integer value. The inexact condition will be set in */
1046 /* the decimal context structure if the number is rounded to */
1047 /* an integer. The invalid operation condition will be set if */
1048 /* the decimal value is outside the range of a 32-bit unsigned int. */
1049 /* */
1050 /* Input: */
1051 /* b Pointer to decimal number structure */
1052 /* pset Pointer to decimal number context structure */
1053 /* Output: */
1054 /* The return value is the 32-bit unsigned integer result */
1055 /*-------------------------------------------------------------------*/
1056 static U32
dfp_number_to_u32(decNumber * b,decContext * pset)1057 dfp_number_to_u32(decNumber *b, decContext *pset)
1058 {
1059 U32 n; /* 32-bit unsigned result */
1060 int32_t scale; /* Scaling factor */
1061 unsigned i; /* Array subscript */
1062 BYTE packed[17]; /* 33-digit packed work area */
1063 decNumber p, c; /* Working decimal numbers */
1064 static U32 mu32 = 0xFFFFFFFFUL; /* Max unsigned integer */
1065 static char mu32zd[]="4294967295"; /* Max unsigned zoned dec */
1066 static BYTE mu32flag = 0; /* 1=mu32dn is initialized */
1067 static decNumber mu32dn; /* Decimal maximum unsigned */
1068 decContext setmax; /* Working context */
1069
1070 /* Prime the decimal number structure representing the maximum
1071 unsigned number representable in 32 bits. Use a 64-bit DFP
1072 working context because this number is too big to be
1073 represented in the 32-bit DFP format */
1074 if (mu32flag == 0)
1075 {
1076 decContextDefault(&setmax, DEC_INIT_DECIMAL64);
1077 decNumberFromString(&mu32dn, mu32zd, &setmax);
1078 mu32flag = 1;
1079 }
1080
1081 /* If operand is a NaN then set invalid operation
1082 and return zero result */
1083 if (decNumberIsNaN(b))
1084 {
1085 pset->status |= DEC_IEEE_854_Invalid_operation;
1086 return (U32)0;
1087 }
1088
1089 /* Round decimal number to integer using current rounding mode */
1090 decNumberToIntegralValue(&p, b, pset);
1091
1092 /* If rounded value is less than zero then set invalid operation
1093 and return zero result */
1094 if (decNumberIsNegative(&p))
1095 {
1096 pset->status |= DEC_IEEE_854_Invalid_operation;
1097 return (U32)0;
1098 }
1099
1100 /* If rounded value is greater than maximum unsigned number
1101 (including where operand is positive infinity) then set
1102 invalid operation and return maximum unsigned result */
1103 decNumberCompare(&c, &p, &mu32dn, pset);
1104 if (decNumberIsNegative(&c) == 0 && decNumberIsZero(&c) == 0)
1105 {
1106 pset->status |= DEC_IEEE_854_Invalid_operation;
1107 return (U32)mu32;
1108 }
1109
1110 /* Raise inexact condition if result was rounded */
1111 decNumberCompare(&c, &p, b, pset);
1112 if (decNumberIsZero(&c) == 0)
1113 {
1114 pset->status |= DEC_IEEE_854_Inexact;
1115 if (decNumberIsNegative(&c) == decNumberIsNegative(b))
1116 pset->status |= DEC_Rounded;
1117 }
1118
1119 /* Convert decimal number structure to packed decimal */
1120 decPackedFromNumber(packed, sizeof(packed), &scale, &p);
1121
1122 /* Convert packed decimal to binary value */
1123 for (i = 0, n = 0; i < sizeof(packed)-1; i++)
1124 {
1125 n = n * 10 + ((packed[i] & 0xF0) >> 4);
1126 n = n * 10 + (packed[i] & 0x0F);
1127 }
1128 n = n * 10 + ((packed[i] & 0xF0) >> 4);
1129 while (scale++) n *= 10;
1130
1131 /* Return 32-bit unsigned result */
1132 return n;
1133
1134 } /* end function dfp_number_to_u32 */
1135
1136 /*-------------------------------------------------------------------*/
1137 /* Convert decimal number to 64-bit unsigned binary integer */
1138 /* */
1139 /* This subroutine is called by the CLGDTR and CLGXTR instructions. */
1140 /* It converts a decimal number structure to a 64-bit unsigned */
1141 /* binary integer value. The inexact condition will be set in */
1142 /* the decimal context structure if the number is rounded to */
1143 /* an integer. The invalid operation condition will be set if */
1144 /* the decimal value is outside the range of a 64-bit unsigned int. */
1145 /* */
1146 /* Input: */
1147 /* b Pointer to decimal number structure */
1148 /* pset Pointer to decimal number context structure */
1149 /* Output: */
1150 /* The return value is the 64-bit unsigned integer result */
1151 /*-------------------------------------------------------------------*/
1152 static U64
dfp_number_to_u64(decNumber * b,decContext * pset)1153 dfp_number_to_u64(decNumber *b, decContext *pset)
1154 {
1155 U64 n; /* 64-bit unsigned result */
1156 int32_t scale; /* Scaling factor */
1157 unsigned i; /* Array subscript */
1158 BYTE packed[17]; /* 33-digit packed work area */
1159 decNumber p, c; /* Working decimal numbers */
1160 static U64 mu64 = 0xFFFFFFFFFFFFFFFFULL; /* Max unsigned int */
1161 static char mu64zd[]="18446744073709551615"; /* Max zoned dec */
1162 static BYTE mu64flag = 0; /* 1=mu64dn is initialized */
1163 static decNumber mu64dn; /* Decimal maximum unsigned */
1164 decContext setmax; /* Working context */
1165
1166 /* Prime the decimal number structure representing the maximum
1167 unsigned number representable in 64 bits. Use a 128-bit DFP
1168 working context because this number is too big to be
1169 represented in the 32-bit or 64-bit DFP format */
1170 if (mu64flag == 0)
1171 {
1172 decContextDefault(&setmax, DEC_INIT_DECIMAL128);
1173 decNumberFromString(&mu64dn, mu64zd, &setmax);
1174 mu64flag = 1;
1175 }
1176
1177 /* If operand is a NaN then set invalid operation
1178 and return zero result */
1179 if (decNumberIsNaN(b))
1180 {
1181 pset->status |= DEC_IEEE_854_Invalid_operation;
1182 return (U64)0;
1183 }
1184
1185 /* Round decimal number to integer using current rounding mode */
1186 decNumberToIntegralValue(&p, b, pset);
1187
1188 /* If rounded value is less than zero then set invalid operation
1189 and return zero result */
1190 if (decNumberIsNegative(&p))
1191 {
1192 pset->status |= DEC_IEEE_854_Invalid_operation;
1193 return (U64)0;
1194 }
1195
1196 /* If rounded value is greater than maximum unsigned number
1197 (including where operand is positive infinity) then set
1198 invalid operation and return maximum unsigned result */
1199 decNumberCompare(&c, &p, &mu64dn, pset);
1200 if (decNumberIsNegative(&c) == 0 && decNumberIsZero(&c) == 0)
1201 {
1202 pset->status |= DEC_IEEE_854_Invalid_operation;
1203 return (U64)mu64;
1204 }
1205
1206 /* Raise inexact condition if result was rounded */
1207 decNumberCompare(&c, &p, b, pset);
1208 if (decNumberIsZero(&c) == 0)
1209 {
1210 pset->status |= DEC_IEEE_854_Inexact;
1211 if (decNumberIsNegative(&c) == decNumberIsNegative(b))
1212 pset->status |= DEC_Rounded;
1213 }
1214
1215 /* Convert decimal number structure to packed decimal */
1216 decPackedFromNumber(packed, sizeof(packed), &scale, &p);
1217
1218 /* Convert packed decimal to binary value */
1219 for (i = 0, n = 0; i < sizeof(packed)-1; i++)
1220 {
1221 n = n * 10 + ((packed[i] & 0xF0) >> 4);
1222 n = n * 10 + (packed[i] & 0x0F);
1223 }
1224 n = n * 10 + ((packed[i] & 0xF0) >> 4);
1225 while (scale++) n *= 10;
1226
1227 /* Return 64-bit unsigned result */
1228 return n;
1229
1230 } /* end function dfp_number_to_u64 */
1231
1232 #define _DFP_FPE_ARCH_INDEPENDENT_
1233 #endif /*!defined(_DFP_FPE_ARCH_INDEPENDENT_)*/
1234 #endif /*defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)*/ /*810*/
1235
1236 #if defined(FEATURE_DFP_ZONED_CONVERSION_FACILITY) /*912*/
1237 #if !defined(_DFP_ZONED_ARCH_INDEPENDENT_)
1238 #define CDZT_MAXLEN 16 /* CDZT maximum operand len */
1239 #define CXZT_MAXLEN 34 /* CXZT maximum operand len */
1240 /*-------------------------------------------------------------------*/
1241 /* Convert zoned decimal to decimal number */
1242 /* */
1243 /* This subroutine is called by the CDZT and CXZT instructions. */
1244 /* It converts a zoned decimal value into a decimal number */
1245 /* structure. The length of the zoned decimal value should not */
1246 /* exceed the maximum number of digits specified in the context. */
1247 /* */
1248 /* Input: */
1249 /* dn Pointer to decimal number structure */
1250 /* zoned zoned decimal input area */
1251 /* len length-1 of zoned decimal input */
1252 /* mask mask field: 0x8=signed */
1253 /* pset Pointer to decimal number context structure */
1254 /* Output: */
1255 /* The decimal number structure is updated. */
1256 /* Return value: 0=success, 1=data exception */
1257 /*-------------------------------------------------------------------*/
1258 static int
dfp_number_from_zoned(decNumber * dn,char * zoned,int len,int mask,decContext * pset)1259 dfp_number_from_zoned(decNumber *dn, char *zoned, int len,
1260 int mask, decContext *pset)
1261 {
1262 int i; /* Array subscript */
1263 int signflag; /* 1=signed decimal operand */
1264 char zwork[1+CXZT_MAXLEN+1]; /* Sign + digits + null */
1265 char *pzw = zwork; /* Addr next byte in zwork */
1266 char c; /* Character work area */
1267
1268 /* Set the signed flag if indicated by the mask */
1269 signflag = (mask & 0x8) ? 1 : 0;
1270
1271 /* Set the sign according to the operand sign code */
1272 if (signflag) {
1273 switch ((zoned[len] & 0xF0) >> 4) {
1274 case 0xB: case 0xD:
1275 *pzw++ = '-'; break;
1276 case 0xA: case 0xC: case 0xE: case 0xF:
1277 break;
1278 default:
1279 /* Data exception if invalid sign code */
1280 return 1;
1281 }
1282 }
1283
1284 /* Convert zoned number to a decimal string */
1285 for (i=0; i <= len; i++)
1286 {
1287 c = zoned[i] & 0x0F;
1288 /* Data exception if invalid digit */
1289 if (c > 0x09) return 1;
1290 *pzw++ = c + '0';
1291 }
1292 *pzw = '\0';
1293
1294 /* Convert decimal string to decimal number structure */
1295 decNumberFromString(dn, zwork, pset);
1296
1297 return 0;
1298
1299 } /* end function dfp_number_from_zoned */
1300
1301 #define CZDT_MAXLEN 16 /* CZDT maximum operand len */
1302 #define CZXT_MAXLEN 34 /* CZXT maximum operand len */
1303 /*-------------------------------------------------------------------*/
1304 /* Convert decimal number to zoned decimal */
1305 /* */
1306 /* This subroutine is called by the CZDT and CZXT instructions. */
1307 /* It converts a decimal number to a zoned decimal string. */
1308 /* */
1309 /* Input: */
1310 /* dn Pointer to decimal number structure */
1311 /* representing original DFP value */
1312 /* dc Pointer to decimal number structure */
1313 /* containing only coeffecient of DFP value */
1314 /* zoned zoned decimal output area */
1315 /* len length-1 of zoned decimal output area */
1316 /* mask mask field: 0x8=signed, 0x4=ASCII, */
1317 /* 0x2=plus sign is F, 0x1=zero is always positive */
1318 /* pset Pointer to decimal number context structure */
1319 /* Output: */
1320 /* The zoned decimal area is updated. */
1321 /* Return value is the condition code: */
1322 /* 0=zero; 1=negative; 2=positive; 3=Inf, NaN, or overflow */
1323 /*-------------------------------------------------------------------*/
1324 static int
dfp_number_to_zoned(decNumber * dn,decNumber * dc,char * zoned,int len,int mask,decContext * pset)1325 dfp_number_to_zoned(decNumber *dn, decNumber *dc, char *zoned, int len,
1326 int mask, decContext *pset)
1327 {
1328 int i; /* Array subscript */
1329 int pad; /* Number of padding bytes */
1330 int cc; /* Condition code */
1331 int sign; /* 1=negative number */
1332 char zwork[MAXDECSTRLEN+64]; /* Decimal string work area */
1333 int zwlen; /* Length of zwork string */
1334 int zwind; /* Index into zwork string */
1335
1336 UNREFERENCED(pset);
1337
1338 /* Determine if the number is negative or positive */
1339 sign = (decNumberIsNegative(dn)) ? 1 : 0;
1340
1341 /* Force plus zero if mask bit 3 is set */
1342 if ((mask & 0x1) && decNumberIsZero(dn)) sign = 0;
1343
1344 /* Convert decimal number to string */
1345 if (decNumberIsNaN(dn) || (decNumberIsInfinite(dn)))
1346 {
1347 /* For NaN or Inf set cc=3 and use coefficient only */
1348 cc = 3;
1349 dc->exponent = 0;
1350 dc->bits &= ~(DECNEG);
1351 decNumberToString(dc, zwork);
1352 } else {
1353 /* For finite numbers set cc=0, 1, or 2 and convert digits */
1354 cc = (decNumberIsZero(dn)) ? 0 :
1355 (decNumberIsNegative(dn)) ? 1 : 2;
1356 dn->exponent = 0;
1357 dn->bits &= ~(DECNEG);
1358 decNumberToString(dn, zwork);
1359 }
1360
1361 /* Calculate the number of padding bytes needed, and set
1362 condition code 3 if significant digits will be lost */
1363 zwlen = (int)(strlen(zwork));
1364 if (zwlen <= len + 1)
1365 {
1366 zwind = 0;
1367 pad = len + 1 - zwlen;
1368 } else {
1369 zwind = zwlen - len - 1;
1370 pad = 0;
1371 cc = 3;
1372 }
1373
1374 /* Copy digits to zoned decimal result area */
1375 for (i = 0; i <= len; i++)
1376 {
1377 /* Pad with zero or copy digit from work string */
1378 zoned[i] = (pad > 0) ? 0x00 : zwork[zwind++] - '0';
1379 if (pad > 0) pad--;
1380 /* Set ASCII or EBCDIC zone according to mask bit 1 */
1381 zoned[i] |= (mask & 0x4) ? 0x30 : 0xF0;
1382 }
1383
1384 /* Replace final zone by EBCDIC sign if mask bit 0 is one */
1385 if (mask & 0x8)
1386 {
1387 /* -ve sign is D, +ve sign is F or C depending on mask bit 2 */
1388 zoned[i-1] &= 0x0F;
1389 zoned[i-1] |= (sign) ? 0xD0 : (mask & 0x2) ? 0xF0 : 0xC0;
1390 }
1391
1392 /* Return the condition code */
1393 return cc;
1394
1395 } /* end function dfp_number_to_zoned */
1396
1397 #define _DFP_ZONED_ARCH_INDEPENDENT_
1398 #endif /*!defined(_DFP_ZONED_ARCH_INDEPENDENT_)*/
1399 #endif /*defined(FEATURE_DFP_ZONED_CONVERSION_FACILITY)*/ /*912*/
1400
1401 /*-------------------------------------------------------------------*/
1402 /* Set rounding mode in decimal context structure */
1403 /* */
1404 /* Input: */
1405 /* pset Pointer to decimal number context structure */
1406 /* mask 4-bit mask value */
1407 /* regs CPU register context */
1408 /* Output: */
1409 /* If mask bit X'08' is one then the rounding mode in the */
1410 /* context structure is set according to the value (0 to 7) */
1411 /* indicated by the low-order three bits of the mask. */
1412 /* If mask bit X'08' is zero then the rounding mode in the */
1413 /* context structure is set according to the value (0 to 7) */
1414 /* of the DRM field in the FPC register. */
1415 /*-------------------------------------------------------------------*/
1416 static inline void
ARCH_DEP(dfp_rounding_mode)1417 ARCH_DEP(dfp_rounding_mode) (decContext *pset, int mask, REGS *regs)
1418 {
1419 BYTE drm; /* Decimal rounding mode */
1420
1421 /* Load DRM from mask or from FPC register */
1422 if (mask & 0x08)
1423 drm = mask & 0x07;
1424 else
1425 drm = (regs->fpc & FPC_DRM) >> FPC_DRM_SHIFT;
1426
1427 /* Set rounding mode according to DRM value */
1428 switch (drm) {
1429 case DRM_RNE: pset->round = DEC_ROUND_HALF_EVEN; break;
1430 case DRM_RTZ: pset->round = DEC_ROUND_DOWN; break;
1431 case DRM_RTPI: pset->round = DEC_ROUND_CEILING; break;
1432 case DRM_RTMI: pset->round = DEC_ROUND_FLOOR; break;
1433 case DRM_RNAZ: pset->round = DEC_ROUND_HALF_UP; break;
1434 case DRM_RNTZ: pset->round = DEC_ROUND_HALF_DOWN; break;
1435 case DRM_RAFZ: pset->round = DEC_ROUND_UP; break;
1436 case DRM_RFSP:
1437 /* Rounding mode DRM_RFSP is not supported by
1438 the decNumber library, so we arbitrarily
1439 convert it to another mode instead... */
1440 pset->round = DEC_ROUND_DOWN; break;
1441 } /* end switch(drm) */
1442
1443 } /* end function dfp_rounding_mode */
1444
1445 /*-------------------------------------------------------------------*/
1446 /* Copy a DFP short register into a decimal32 structure */
1447 /* */
1448 /* Input: */
1449 /* rn FP register number */
1450 /* xp Pointer to decimal32 structure */
1451 /* regs CPU register context */
1452 /*-------------------------------------------------------------------*/
1453 static inline void
ARCH_DEP(dfp_reg_to_decimal32)1454 ARCH_DEP(dfp_reg_to_decimal32) (int rn, decimal32 *xp, REGS *regs)
1455 {
1456 int i; /* FP register subscript */
1457 FW *fwp; /* Fullword pointer */
1458
1459 i = FPR2I(rn); /* Register index */
1460 fwp = (FW*)xp; /* Convert to FW pointer */
1461 fwp->F = regs->fpr[i]; /* Copy FPR bits 0-31 */
1462
1463 } /* end function dfp_reg_to_decimal32 */
1464
1465 /*-------------------------------------------------------------------*/
1466 /* Load a DFP short register from a decimal32 structure */
1467 /* */
1468 /* Input: */
1469 /* rn FP register number (left register of pair) */
1470 /* xp Pointer to decimal32 structure */
1471 /* regs CPU register context */
1472 /*-------------------------------------------------------------------*/
1473 static inline void
ARCH_DEP(dfp_reg_from_decimal32)1474 ARCH_DEP(dfp_reg_from_decimal32) (int rn, decimal32 *xp, REGS *regs)
1475 {
1476 int i; /* FP register subscript */
1477 FW *fwp; /* Fullword pointer */
1478
1479 i = FPR2I(rn); /* Register index */
1480 fwp = (FW*)xp; /* Convert to FW pointer */
1481 regs->fpr[i] = fwp->F; /* Load FPR bits 0-31 */
1482
1483 } /* end function dfp_reg_from_decimal32 */
1484
1485 /*-------------------------------------------------------------------*/
1486 /* Copy a DFP long register into a decimal64 structure */
1487 /* */
1488 /* Input: */
1489 /* rn FP register number */
1490 /* xp Pointer to decimal64 structure */
1491 /* regs CPU register context */
1492 /*-------------------------------------------------------------------*/
1493 static inline void
ARCH_DEP(dfp_reg_to_decimal64)1494 ARCH_DEP(dfp_reg_to_decimal64) (int rn, decimal64 *xp, REGS *regs)
1495 {
1496 int i; /* FP register subscript */
1497 DW *dwp; /* Doubleword pointer */
1498
1499 i = FPR2I(rn); /* Register index */
1500 dwp = (DW*)xp; /* Convert to DW pointer */
1501 dwp->F.H.F = regs->fpr[i]; /* Copy FPR bits 0-31 */
1502 dwp->F.L.F = regs->fpr[i+1]; /* Copy FPR bits 32-63 */
1503
1504 } /* end function dfp_reg_to_decimal64 */
1505
1506 /*-------------------------------------------------------------------*/
1507 /* Load a DFP long register from a decimal64 structure */
1508 /* */
1509 /* Input: */
1510 /* rn FP register number (left register of pair) */
1511 /* xp Pointer to decimal64 structure */
1512 /* regs CPU register context */
1513 /*-------------------------------------------------------------------*/
1514 static inline void
ARCH_DEP(dfp_reg_from_decimal64)1515 ARCH_DEP(dfp_reg_from_decimal64) (int rn, decimal64 *xp, REGS *regs)
1516 {
1517 int i; /* FP register subscript */
1518 DW *dwp; /* Doubleword pointer */
1519
1520 i = FPR2I(rn); /* Register index */
1521 dwp = (DW*)xp; /* Convert to DW pointer */
1522 regs->fpr[i] = dwp->F.H.F; /* Load FPR bits 0-31 */
1523 regs->fpr[i+1] = dwp->F.L.F; /* Load FPR bits 32-63 */
1524
1525 } /* end function dfp_reg_from_decimal64 */
1526
1527 /*-------------------------------------------------------------------*/
1528 /* Copy a DFP extended register into a decimal128 structure */
1529 /* */
1530 /* Input: */
1531 /* rn FP register number (left register of pair) */
1532 /* xp Pointer to decimal128 structure */
1533 /* regs CPU register context */
1534 /*-------------------------------------------------------------------*/
1535 static inline void
ARCH_DEP(dfp_reg_to_decimal128)1536 ARCH_DEP(dfp_reg_to_decimal128) (int rn, decimal128 *xp, REGS *regs)
1537 {
1538 int i, j; /* FP register subscripts */
1539 QW *qwp; /* Quadword pointer */
1540
1541 i = FPR2I(rn); /* Left register index */
1542 j = i + FPREX; /* Right register index */
1543 qwp = (QW*)xp; /* Convert to QW pointer */
1544 qwp->F.HH.F = regs->fpr[i]; /* Copy FPR bits 0-31 */
1545 qwp->F.HL.F = regs->fpr[i+1]; /* Copy FPR bits 32-63 */
1546 qwp->F.LH.F = regs->fpr[j]; /* Copy FPR bits 64-95 */
1547 qwp->F.LL.F = regs->fpr[j+1]; /* Copy FPR bits 96-127 */
1548
1549 } /* end function dfp_reg_to_decimal128 */
1550
1551 /*-------------------------------------------------------------------*/
1552 /* Load a DFP extended register from a decimal128 structure */
1553 /* */
1554 /* Input: */
1555 /* rn FP register number (left register of pair) */
1556 /* xp Pointer to decimal128 structure */
1557 /* regs CPU register context */
1558 /*-------------------------------------------------------------------*/
1559 static inline void
ARCH_DEP(dfp_reg_from_decimal128)1560 ARCH_DEP(dfp_reg_from_decimal128) (int rn, decimal128 *xp, REGS *regs)
1561 {
1562 int i, j; /* FP register subscripts */
1563 QW *qwp; /* Quadword pointer */
1564
1565 i = FPR2I(rn); /* Left register index */
1566 j = i + FPREX; /* Right register index */
1567 qwp = (QW*)xp; /* Convert to QW pointer */
1568 regs->fpr[i] = qwp->F.HH.F; /* Load FPR bits 0-31 */
1569 regs->fpr[i+1] = qwp->F.HL.F; /* Load FPR bits 32-63 */
1570 regs->fpr[j] = qwp->F.LH.F; /* Load FPR bits 64-95 */
1571 regs->fpr[j+1] = qwp->F.LL.F; /* Load FPR bits 96-127 */
1572
1573 } /* end function dfp_reg_from_decimal128 */
1574
1575 /*-------------------------------------------------------------------*/
1576 /* Check for DFP exception conditions */
1577 /* */
1578 /* This subroutine is called by the DFP instruction processing */
1579 /* routines after the calculation has been performed but before */
1580 /* the result is loaded into the result register (or before any */
1581 /* storage location is updated, as the case may be). */
1582 /* */
1583 /* The purpose of this subroutine is to check whether any DFP */
1584 /* exception conditions are indicated by the decimal context */
1585 /* structure, and to initiate the appropriate action if so. */
1586 /* */
1587 /* Input: */
1588 /* set Decimal number context */
1589 /* regs CPU register context */
1590 /* */
1591 /* Output: */
1592 /* Return value is DXC (data exception code) or zero. */
1593 /* */
1594 /* When no exception conditions are indicated, the return value */
1595 /* is zero indicating that the instruction may proceed normally. */
1596 /* */
1597 /* When an exception condition exists and the corresponding mask */
1598 /* bit in the FPC register is zero, then the corresponding flag */
1599 /* bit is set in the FPC register. The return value is zero to */
1600 /* indicate that the instruction may proceed normally. */
1601 /* */
1602 /* When an exception condition exists and the corresponding mask */
1603 /* bit in the FPC register is one, then the DXC is set according */
1604 /* to the type of exception, and one of two actions is taken: */
1605 /* - if the exception is of a type which causes the instruction */
1606 /* to be suppressed, then this subroutine raises a program */
1607 /* exception and does not return to the calling instruction */
1608 /* - if the exception is of a type which causes the instruction */
1609 /* to be completed, then this subroutine returns with the */
1610 /* DXC code as its return value. The calling instruction will */
1611 /* then raise a program exception after storing its results. */
1612 /*-------------------------------------------------------------------*/
1613 static BYTE
ARCH_DEP(dfp_status_check)1614 ARCH_DEP(dfp_status_check) (decContext *pset, REGS *regs)
1615 {
1616 BYTE dxc = 0; /* Data exception code */
1617 int suppress = 0; /* 1=suppress, 0=complete */
1618
1619 if (pset->status & DEC_IEEE_854_Invalid_operation)
1620 {
1621 /* An IEEE-invalid-operation condition was recognized */
1622 if ((regs->fpc & FPC_MASK_IMI) == 0)
1623 {
1624 regs->fpc |= FPC_FLAG_SFI;
1625 }
1626 else
1627 {
1628 dxc = DXC_IEEE_INVALID_OP;
1629 suppress = 1;
1630 }
1631 }
1632 else if (pset->status & DEC_IEEE_854_Division_by_zero)
1633 {
1634 /* An IEEE-division-by-zero condition was recognized */
1635 if ((regs->fpc & FPC_MASK_IMZ) == 0)
1636 {
1637 /* Division-by-zero mask is zero */
1638 regs->fpc |= FPC_FLAG_SFZ;
1639 }
1640 else
1641 {
1642 /* Division-by-zero mask is one */
1643 dxc = DXC_IEEE_DIV_ZERO;
1644 suppress = 1;
1645 }
1646 }
1647 else if (pset->status & DEC_IEEE_854_Overflow)
1648 {
1649 /* An IEEE-overflow condition was recognized */
1650 if ((regs->fpc & FPC_MASK_IMO) == 0)
1651 {
1652 /* Overflow mask is zero */
1653 regs->fpc |= FPC_FLAG_SFO;
1654 }
1655 else
1656 {
1657 /* Overflow mask is one */
1658 dxc = (pset->status & DEC_IEEE_854_Inexact) ?
1659 ((pset->status & DEC_Rounded) ?
1660 DXC_IEEE_OF_INEX_INCR :
1661 DXC_IEEE_OF_INEX_TRUNC ) :
1662 DXC_IEEE_OF_EXACT ;
1663 }
1664 }
1665 else if (pset->status & DEC_IEEE_854_Underflow)
1666 {
1667 /* An IEEE-underflow condition was recognized */
1668 if ((regs->fpc & FPC_MASK_IMU) == 0)
1669 {
1670 /* Underflow mask is zero */
1671 if (pset->status & DEC_IEEE_854_Inexact)
1672 {
1673 if ((regs->fpc & FPC_MASK_IMX) == 0)
1674 {
1675 /* Inexact result with inexact mask zero */
1676 regs->fpc |= (FPC_FLAG_SFU | FPC_FLAG_SFX);
1677 }
1678 else
1679 {
1680 /* Inexact result with inexact mask one */
1681 regs->fpc |= FPC_FLAG_SFU;
1682 dxc = (pset->status & DEC_Rounded) ?
1683 DXC_IEEE_INEXACT_INCR :
1684 DXC_IEEE_INEXACT_TRUNC ;
1685 }
1686 }
1687 }
1688 else
1689 {
1690 /* Underflow mask is one */
1691 if (pset->status & DEC_IEEE_854_Inexact)
1692 {
1693 /* Underflow with inexact result */
1694 dxc = (pset->status & DEC_Rounded) ?
1695 DXC_IEEE_UF_INEX_INCR :
1696 DXC_IEEE_UF_INEX_TRUNC ;
1697 }
1698 else
1699 {
1700 /* Underflow with exact result */
1701 dxc = DXC_IEEE_UF_EXACT;
1702 }
1703 }
1704 }
1705 else if (pset->status & DEC_IEEE_854_Inexact)
1706 {
1707 /* An IEEE-inexact condition was recognized */
1708 if ((regs->fpc & FPC_MASK_IMX) == 0)
1709 {
1710 /* Inexact mask is zero */
1711 regs->fpc |= FPC_FLAG_SFX;
1712 }
1713 else
1714 {
1715 /* Inexact mask is one */
1716 dxc = (pset->status & DEC_Rounded) ?
1717 DXC_IEEE_INEXACT_INCR :
1718 DXC_IEEE_INEXACT_TRUNC ;
1719 }
1720 }
1721
1722 /* If suppression is indicated, raise a data exception */
1723 if (suppress)
1724 {
1725 regs->dxc = dxc;
1726 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
1727 }
1728
1729 /* Otherwise return to complete the instruction */
1730 return dxc;
1731
1732 } /* end function dfp_status_check */
1733
1734
1735 /*-------------------------------------------------------------------*/
1736 /* B3DA AXTR - Add DFP Extended Register [RRR] */
1737 /*-------------------------------------------------------------------*/
DEF_INST(add_dfp_ext_reg)1738 DEF_INST(add_dfp_ext_reg)
1739 {
1740 int r1, r2, r3; /* Values of R fields */
1741 decimal128 x1, x2, x3; /* Extended DFP values */
1742 decNumber d1, d2, d3; /* Working decimal numbers */
1743 decContext set; /* Working context */
1744 BYTE dxc; /* Data exception code */
1745
1746 RRR(inst, regs, r1, r2, r3);
1747 DFPINST_CHECK(regs);
1748 DFPREGPAIR3_CHECK(r1, r2, r3, regs);
1749
1750 /* Initialise the context for extended DFP */
1751 decContextDefault(&set, DEC_INIT_DECIMAL128);
1752 ARCH_DEP(dfp_rounding_mode)(&set, 0, regs);
1753
1754 /* Add FP register r3 to FP register r2 */
1755 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
1756 ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs);
1757 decimal128ToNumber(&x2, &d2);
1758 decimal128ToNumber(&x3, &d3);
1759 decNumberAdd(&d1, &d2, &d3, &set);
1760 decimal128FromNumber(&x1, &d1, &set);
1761
1762 /* Check for exception condition */
1763 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
1764
1765 /* Load result into FP register r1 */
1766 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
1767
1768 /* Set condition code */
1769 regs->psw.cc = decNumberIsNaN(&d1) ? 3 :
1770 decNumberIsZero(&d1) ? 0 :
1771 decNumberIsNegative(&d1) ? 1 : 2;
1772
1773 /* Raise data exception if error occurred */
1774 if (dxc != 0)
1775 {
1776 regs->dxc = dxc;
1777 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
1778 }
1779
1780 } /* end DEF_INST(add_dfp_ext_reg) */
1781
1782
1783 /*-------------------------------------------------------------------*/
1784 /* B3D2 ADTR - Add DFP Long Register [RRR] */
1785 /*-------------------------------------------------------------------*/
DEF_INST(add_dfp_long_reg)1786 DEF_INST(add_dfp_long_reg)
1787 {
1788 int r1, r2, r3; /* Values of R fields */
1789 decimal64 x1, x2, x3; /* Long DFP values */
1790 decNumber d1, d2, d3; /* Working decimal numbers */
1791 decContext set; /* Working context */
1792 BYTE dxc; /* Data exception code */
1793
1794 RRR(inst, regs, r1, r2, r3);
1795 DFPINST_CHECK(regs);
1796
1797 /* Initialise the context for long DFP */
1798 decContextDefault(&set, DEC_INIT_DECIMAL64);
1799 ARCH_DEP(dfp_rounding_mode)(&set, 0, regs);
1800
1801 /* Add FP register r3 to FP register r2 */
1802 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
1803 ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs);
1804 decimal64ToNumber(&x2, &d2);
1805 decimal64ToNumber(&x3, &d3);
1806 decNumberAdd(&d1, &d2, &d3, &set);
1807 decimal64FromNumber(&x1, &d1, &set);
1808
1809 /* Check for exception condition */
1810 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
1811
1812 /* Load result into FP register r1 */
1813 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
1814
1815 /* Set condition code */
1816 regs->psw.cc = decNumberIsNaN(&d1) ? 3 :
1817 decNumberIsZero(&d1) ? 0 :
1818 decNumberIsNegative(&d1) ? 1 : 2;
1819
1820 /* Raise data exception if error occurred */
1821 if (dxc != 0)
1822 {
1823 regs->dxc = dxc;
1824 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
1825 }
1826
1827 } /* end DEF_INST(add_dfp_long_reg) */
1828
1829
1830 /*-------------------------------------------------------------------*/
1831 /* B3EC CXTR - Compare DFP Extended Register [RRE] */
1832 /*-------------------------------------------------------------------*/
DEF_INST(compare_dfp_ext_reg)1833 DEF_INST(compare_dfp_ext_reg)
1834 {
1835 int r1, r2; /* Values of R fields */
1836 decimal128 x1, x2; /* Extended DFP values */
1837 decNumber d1, d2, dr; /* Working decimal numbers */
1838 decContext set; /* Working context */
1839 BYTE dxc; /* Data exception code */
1840
1841 RRE(inst, regs, r1, r2);
1842 DFPINST_CHECK(regs);
1843 DFPREGPAIR2_CHECK(r1, r2, regs);
1844
1845 /* Initialise the context for extended DFP */
1846 decContextDefault(&set, DEC_INIT_DECIMAL128);
1847
1848 /* Compare FP register r1 with FP register r2 */
1849 ARCH_DEP(dfp_reg_to_decimal128)(r1, &x1, regs);
1850 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
1851 decimal128ToNumber(&x1, &d1);
1852 decimal128ToNumber(&x2, &d2);
1853 decNumberCompare(&dr, &d1, &d2, &set);
1854
1855 /* Check for exception condition */
1856 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
1857
1858 /* Set condition code */
1859 regs->psw.cc = decNumberIsNaN(&dr) ? 3 :
1860 decNumberIsZero(&dr) ? 0 :
1861 decNumberIsNegative(&dr) ? 1 : 2;
1862
1863 /* Raise data exception if error occurred */
1864 if (dxc != 0)
1865 {
1866 regs->dxc = dxc;
1867 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
1868 }
1869
1870 } /* end DEF_INST(compare_dfp_ext_reg) */
1871
1872
1873 /*-------------------------------------------------------------------*/
1874 /* B3E4 CDTR - Compare DFP Long Register [RRE] */
1875 /*-------------------------------------------------------------------*/
DEF_INST(compare_dfp_long_reg)1876 DEF_INST(compare_dfp_long_reg)
1877 {
1878 int r1, r2; /* Values of R fields */
1879 decimal64 x1, x2; /* Long DFP values */
1880 decNumber d1, d2, dr; /* Working decimal numbers */
1881 decContext set; /* Working context */
1882 BYTE dxc; /* Data exception code */
1883
1884 RRE(inst, regs, r1, r2);
1885 DFPINST_CHECK(regs);
1886
1887 /* Initialise the context for long DFP */
1888 decContextDefault(&set, DEC_INIT_DECIMAL64);
1889
1890 /* Compare FP register r1 with FP register r2 */
1891 ARCH_DEP(dfp_reg_to_decimal64)(r1, &x1, regs);
1892 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
1893 decimal64ToNumber(&x1, &d1);
1894 decimal64ToNumber(&x2, &d2);
1895 decNumberCompare(&dr, &d1, &d2, &set);
1896
1897 /* Check for exception condition */
1898 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
1899
1900 /* Set condition code */
1901 regs->psw.cc = decNumberIsNaN(&dr) ? 3 :
1902 decNumberIsZero(&dr) ? 0 :
1903 decNumberIsNegative(&dr) ? 1 : 2;
1904
1905 /* Raise data exception if error occurred */
1906 if (dxc != 0)
1907 {
1908 regs->dxc = dxc;
1909 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
1910 }
1911
1912 } /* end DEF_INST(compare_dfp_long_reg) */
1913
1914
1915 /*-------------------------------------------------------------------*/
1916 /* B3E8 KXTR - Compare and Signal DFP Extended Register [RRE] */
1917 /*-------------------------------------------------------------------*/
DEF_INST(compare_and_signal_dfp_ext_reg)1918 DEF_INST(compare_and_signal_dfp_ext_reg)
1919 {
1920 int r1, r2; /* Values of R fields */
1921 decimal128 x1, x2; /* Extended DFP values */
1922 decNumber d1, d2, dr; /* Working decimal numbers */
1923 decContext set; /* Working context */
1924 BYTE dxc; /* Data exception code */
1925
1926 RRE(inst, regs, r1, r2);
1927 DFPINST_CHECK(regs);
1928 DFPREGPAIR2_CHECK(r1, r2, regs);
1929
1930 /* Initialise the context for extended DFP */
1931 decContextDefault(&set, DEC_INIT_DECIMAL128);
1932
1933 /* Compare FP register r1 with FP register r2 */
1934 ARCH_DEP(dfp_reg_to_decimal128)(r1, &x1, regs);
1935 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
1936 decimal128ToNumber(&x1, &d1);
1937 decimal128ToNumber(&x2, &d2);
1938 decNumberCompare(&dr, &d1, &d2, &set);
1939
1940 /* Force signaling condition if result is a NaN */
1941 if (decNumberIsNaN(&dr))
1942 set.status |= DEC_IEEE_854_Invalid_operation;
1943
1944 /* Check for exception condition */
1945 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
1946
1947 /* Set condition code */
1948 regs->psw.cc = decNumberIsNaN(&dr) ? 3 :
1949 decNumberIsZero(&dr) ? 0 :
1950 decNumberIsNegative(&dr) ? 1 : 2;
1951
1952 /* Raise data exception if error occurred */
1953 if (dxc != 0)
1954 {
1955 regs->dxc = dxc;
1956 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
1957 }
1958
1959 } /* end DEF_INST(compare_and_signal_dfp_ext_reg) */
1960
1961
1962 /*-------------------------------------------------------------------*/
1963 /* B3E0 KDTR - Compare and Signal DFP Long Register [RRE] */
1964 /*-------------------------------------------------------------------*/
DEF_INST(compare_and_signal_dfp_long_reg)1965 DEF_INST(compare_and_signal_dfp_long_reg)
1966 {
1967 int r1, r2; /* Values of R fields */
1968 decimal64 x1, x2; /* Long DFP values */
1969 decNumber d1, d2, dr; /* Working decimal numbers */
1970 decContext set; /* Working context */
1971 BYTE dxc; /* Data exception code */
1972
1973 RRE(inst, regs, r1, r2);
1974 DFPINST_CHECK(regs);
1975
1976 /* Initialise the context for long DFP */
1977 decContextDefault(&set, DEC_INIT_DECIMAL64);
1978
1979 /* Compare FP register r1 with FP register r2 */
1980 ARCH_DEP(dfp_reg_to_decimal64)(r1, &x1, regs);
1981 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
1982 decimal64ToNumber(&x1, &d1);
1983 decimal64ToNumber(&x2, &d2);
1984 decNumberCompare(&dr, &d1, &d2, &set);
1985
1986 /* Force signaling condition if result is a NaN */
1987 if (decNumberIsNaN(&dr))
1988 set.status |= DEC_IEEE_854_Invalid_operation;
1989
1990 /* Check for exception condition */
1991 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
1992
1993 /* Set condition code */
1994 regs->psw.cc = decNumberIsNaN(&dr) ? 3 :
1995 decNumberIsZero(&dr) ? 0 :
1996 decNumberIsNegative(&dr) ? 1 : 2;
1997
1998 /* Raise data exception if error occurred */
1999 if (dxc != 0)
2000 {
2001 regs->dxc = dxc;
2002 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2003 }
2004
2005 } /* end DEF_INST(compare_and_signal_dfp_long_reg) */
2006
2007
2008 /*-------------------------------------------------------------------*/
2009 /* B3FC CEXTR - Compare Exponent DFP Extended Register [RRE] */
2010 /*-------------------------------------------------------------------*/
DEF_INST(compare_exponent_dfp_ext_reg)2011 DEF_INST(compare_exponent_dfp_ext_reg)
2012 {
2013 int r1, r2; /* Values of R fields */
2014 decimal128 x1, x2; /* Extended DFP values */
2015 decNumber d1, d2; /* Working decimal numbers */
2016 decContext set; /* Working context */
2017
2018 RRE(inst, regs, r1, r2);
2019 DFPINST_CHECK(regs);
2020 DFPREGPAIR2_CHECK(r1, r2, regs);
2021
2022 /* Initialise the context for extended DFP */
2023 decContextDefault(&set, DEC_INIT_DECIMAL128);
2024
2025 /* Convert FP register values to numbers */
2026 ARCH_DEP(dfp_reg_to_decimal128)(r1, &x1, regs);
2027 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
2028 decimal128ToNumber(&x1, &d1);
2029 decimal128ToNumber(&x2, &d2);
2030
2031 /* Compare exponents and set condition code */
2032 regs->psw.cc = dfp_compare_exponent(&d1, &d2);
2033
2034 } /* end DEF_INST(compare_exponent_dfp_ext_reg) */
2035
2036
2037 /*-------------------------------------------------------------------*/
2038 /* B3F4 CEDTR - Compare Exponent DFP Long Register [RRE] */
2039 /*-------------------------------------------------------------------*/
DEF_INST(compare_exponent_dfp_long_reg)2040 DEF_INST(compare_exponent_dfp_long_reg)
2041 {
2042 int r1, r2; /* Values of R fields */
2043 decimal64 x1, x2; /* Long DFP values */
2044 decNumber d1, d2; /* Working decimal numbers */
2045 decContext set; /* Working context */
2046
2047 RRE(inst, regs, r1, r2);
2048 DFPINST_CHECK(regs);
2049
2050 /* Initialise the context for long DFP */
2051 decContextDefault(&set, DEC_INIT_DECIMAL64);
2052
2053 /* Convert FP register values to numbers */
2054 ARCH_DEP(dfp_reg_to_decimal64)(r1, &x1, regs);
2055 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
2056 decimal64ToNumber(&x1, &d1);
2057 decimal64ToNumber(&x2, &d2);
2058
2059 /* Compare exponents and set condition code */
2060 regs->psw.cc = dfp_compare_exponent(&d1, &d2);
2061
2062 } /* end DEF_INST(compare_exponent_dfp_long_reg) */
2063
2064
2065 #if defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY) /*810*/
2066 /*-------------------------------------------------------------------*/
2067 /* B959 CXFTR - Convert from fixed 32 to DFP Extended Register [RRF] */
2068 /*-------------------------------------------------------------------*/
DEF_INST(convert_fix32_to_dfp_ext_reg)2069 DEF_INST(convert_fix32_to_dfp_ext_reg)
2070 {
2071 int r1, r2; /* Values of R fields */
2072 int m3, m4; /* Values of M fields */
2073 S32 n2; /* Value of R2 register */
2074 decimal128 x1; /* Extended DFP value */
2075 decNumber d1; /* Working decimal number */
2076 decContext set; /* Working context */
2077
2078 RRF_MM(inst, regs, r1, r2, m3, m4);
2079 DFPINST_CHECK(regs);
2080 DFPREGPAIR_CHECK(r1, regs);
2081
2082 /* Initialise the context for extended DFP */
2083 decContextDefault(&set, DEC_INIT_DECIMAL128);
2084 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2085
2086 /* Load 32-bit binary integer value from r2 register */
2087 n2 = (S32)(regs->GR_L(r2));
2088
2089 /* Convert binary integer to extended DFP format */
2090 dfp_number_from_fix32(&d1, n2, &set);
2091 decimal128FromNumber(&x1, &d1, &set);
2092
2093 /* Load result into FP register r1 */
2094 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
2095
2096 } /* end DEF_INST(convert_fix32_to_dfp_ext_reg) */
2097
2098
2099 /*-------------------------------------------------------------------*/
2100 /* B951 CDFTR - Convert from fixed 32 to DFP Long Register [RRF] */
2101 /*-------------------------------------------------------------------*/
DEF_INST(convert_fix32_to_dfp_long_reg)2102 DEF_INST(convert_fix32_to_dfp_long_reg)
2103 {
2104 int r1, r2; /* Values of R fields */
2105 int m3, m4; /* Values of M fields */
2106 S32 n2; /* Value of R2 register */
2107 decimal64 x1; /* Long DFP value */
2108 decNumber d1; /* Working decimal number */
2109 decContext set; /* Working context */
2110 BYTE dxc; /* Data exception code */
2111
2112 RRF_MM(inst, regs, r1, r2, m3, m4);
2113 DFPINST_CHECK(regs);
2114
2115 /* Initialise the context for long DFP */
2116 decContextDefault(&set, DEC_INIT_DECIMAL64);
2117 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2118
2119 /* Load 32-bit binary integer value from r2 register */
2120 n2 = (S32)(regs->GR_L(r2));
2121
2122 /* Convert binary integer to long DFP format */
2123 dfp_number_from_fix32(&d1, n2, &set);
2124 decimal64FromNumber(&x1, &d1, &set);
2125
2126 /* Check for exception condition */
2127 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
2128
2129 /* Load result into FP register r1 */
2130 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
2131
2132 } /* end DEF_INST(convert_fix32_to_dfp_long_reg) */
2133
2134
2135 /*-------------------------------------------------------------------*/
2136 /* B95B CXLFTR - Convert from unsigned 32 to DFP Ext Register [RRF] */
2137 /*-------------------------------------------------------------------*/
DEF_INST(convert_u32_to_dfp_ext_reg)2138 DEF_INST(convert_u32_to_dfp_ext_reg)
2139 {
2140 int r1, r2; /* Values of R fields */
2141 int m3, m4; /* Values of M fields */
2142 U32 n2; /* Value of R2 register */
2143 decimal128 x1; /* Extended DFP value */
2144 decNumber d1; /* Working decimal number */
2145 decContext set; /* Working context */
2146
2147 RRF_MM(inst, regs, r1, r2, m3, m4);
2148 DFPINST_CHECK(regs);
2149 DFPREGPAIR_CHECK(r1, regs);
2150
2151 /* Initialise the context for extended DFP */
2152 decContextDefault(&set, DEC_INIT_DECIMAL128);
2153 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2154
2155 /* Load 32-bit unsigned value from r2 register */
2156 n2 = regs->GR_L(r2);
2157
2158 /* Convert unsigned binary integer to extended DFP format */
2159 dfp_number_from_u32(&d1, n2, &set);
2160 decimal128FromNumber(&x1, &d1, &set);
2161
2162 /* Load result into FP register r1 */
2163 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
2164
2165 } /* end DEF_INST(convert_u32_to_dfp_ext_reg) */
2166
2167
2168 /*-------------------------------------------------------------------*/
2169 /* B953 CDLFTR - Convert from unsigned 32 to DFP Long Register [RRF] */
2170 /*-------------------------------------------------------------------*/
DEF_INST(convert_u32_to_dfp_long_reg)2171 DEF_INST(convert_u32_to_dfp_long_reg)
2172 {
2173 int r1, r2; /* Values of R fields */
2174 int m3, m4; /* Values of M fields */
2175 U32 n2; /* Value of R2 register */
2176 decimal64 x1; /* Long DFP value */
2177 decNumber d1; /* Working decimal number */
2178 decContext set; /* Working context */
2179 BYTE dxc; /* Data exception code */
2180
2181 RRF_MM(inst, regs, r1, r2, m3, m4);
2182 DFPINST_CHECK(regs);
2183
2184 /* Initialise the context for long DFP */
2185 decContextDefault(&set, DEC_INIT_DECIMAL64);
2186 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2187
2188 /* Load 32-bit unsigned value from r2 register */
2189 n2 = regs->GR_L(r2);
2190
2191 /* Convert unsigned binary integer to long DFP format */
2192 dfp_number_from_u32(&d1, n2, &set);
2193 decimal64FromNumber(&x1, &d1, &set);
2194
2195 /* Check for exception condition */
2196 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
2197
2198 /* Load result into FP register r1 */
2199 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
2200
2201 } /* end DEF_INST(convert_u32_to_dfp_long_reg) */
2202 #endif /*defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)*/ /*810*/
2203
2204
2205 /*-------------------------------------------------------------------*/
2206 /* B3F9 CXGTR - Convert from fixed 64 to DFP Extended Register [RRE] */
2207 /*-------------------------------------------------------------------*/
DEF_INST(convert_fix64_to_dfp_ext_reg)2208 DEF_INST(convert_fix64_to_dfp_ext_reg)
2209 {
2210 int r1, r2; /* Values of R fields */
2211 S64 n2; /* Value of R2 register */
2212 decimal128 x1; /* Extended DFP value */
2213 decNumber d1; /* Working decimal number */
2214 decContext set; /* Working context */
2215
2216 RRE(inst, regs, r1, r2);
2217 DFPINST_CHECK(regs);
2218 DFPREGPAIR_CHECK(r1, regs);
2219
2220 /* Initialise the context for extended DFP */
2221 decContextDefault(&set, DEC_INIT_DECIMAL128);
2222 ARCH_DEP(dfp_rounding_mode)(&set, 0, regs);
2223
2224 /* Load 64-bit binary integer value from r2 register */
2225 n2 = (S64)(regs->GR_G(r2));
2226
2227 /* Convert binary integer to extended DFP format */
2228 dfp_number_from_fix64(&d1, n2, &set);
2229 decimal128FromNumber(&x1, &d1, &set);
2230
2231 /* Load result into FP register r1 */
2232 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
2233
2234 } /* end DEF_INST(convert_fix64_to_dfp_ext_reg) */
2235
2236
2237 /*-------------------------------------------------------------------*/
2238 /* B3F1 CDGTR - Convert from fixed 64 to DFP Long Register [RRE] */
2239 /*-------------------------------------------------------------------*/
DEF_INST(convert_fix64_to_dfp_long_reg)2240 DEF_INST(convert_fix64_to_dfp_long_reg)
2241 {
2242 int r1, r2; /* Values of R fields */
2243 S64 n2; /* Value of R2 register */
2244 decimal64 x1; /* Long DFP value */
2245 decNumber d1; /* Working decimal number */
2246 decContext set; /* Working context */
2247 BYTE dxc; /* Data exception code */
2248
2249 RRE(inst, regs, r1, r2);
2250 DFPINST_CHECK(regs);
2251
2252 /* Initialise the context for long DFP */
2253 decContextDefault(&set, DEC_INIT_DECIMAL64);
2254 ARCH_DEP(dfp_rounding_mode)(&set, 0, regs);
2255
2256 /* Load 64-bit binary integer value from r2 register */
2257 n2 = (S64)(regs->GR_G(r2));
2258
2259 /* Convert binary integer to long DFP format */
2260 dfp_number_from_fix64(&d1, n2, &set);
2261 decimal64FromNumber(&x1, &d1, &set);
2262
2263 /* Check for exception condition */
2264 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
2265
2266 /* Load result into FP register r1 */
2267 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
2268
2269 /* Raise data exception if error occurred */
2270 if (dxc != 0)
2271 {
2272 regs->dxc = dxc;
2273 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2274 }
2275
2276 } /* end DEF_INST(convert_fix64_to_dfp_long_reg) */
2277
2278
2279 #if defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY) /*810*/
2280 /*-------------------------------------------------------------------*/
2281 /* B95A CXLGTR - Convert from unsigned 64 to DFP Ext Register [RRF] */
2282 /*-------------------------------------------------------------------*/
DEF_INST(convert_u64_to_dfp_ext_reg)2283 DEF_INST(convert_u64_to_dfp_ext_reg)
2284 {
2285 int r1, r2; /* Values of R fields */
2286 int m3, m4; /* Values of M fields */
2287 U64 n2; /* Value of R2 register */
2288 decimal128 x1; /* Extended DFP value */
2289 decNumber d1; /* Working decimal number */
2290 decContext set; /* Working context */
2291
2292 RRF_MM(inst, regs, r1, r2, m3, m4);
2293 DFPINST_CHECK(regs);
2294 DFPREGPAIR_CHECK(r1, regs);
2295
2296 /* Initialise the context for extended DFP */
2297 decContextDefault(&set, DEC_INIT_DECIMAL128);
2298 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2299
2300 /* Load 64-bit unsigned value from r2 register */
2301 n2 = regs->GR_G(r2);
2302
2303 /* Convert unsigned binary integer to extended DFP format */
2304 dfp_number_from_u64(&d1, n2, &set);
2305 decimal128FromNumber(&x1, &d1, &set);
2306
2307 /* Load result into FP register r1 */
2308 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
2309
2310 } /* end DEF_INST(convert_u64_to_dfp_ext_reg) */
2311
2312
2313 /*-------------------------------------------------------------------*/
2314 /* B952 CDLGTR - Convert from unsigned 64 to DFP Long Register [RRF] */
2315 /*-------------------------------------------------------------------*/
DEF_INST(convert_u64_to_dfp_long_reg)2316 DEF_INST(convert_u64_to_dfp_long_reg)
2317 {
2318 int r1, r2; /* Values of R fields */
2319 int m3, m4; /* Values of M fields */
2320 U64 n2; /* Value of R2 register */
2321 decimal64 x1; /* Long DFP value */
2322 decNumber d1; /* Working decimal number */
2323 decContext set; /* Working context */
2324 BYTE dxc; /* Data exception code */
2325
2326 RRF_MM(inst, regs, r1, r2, m3, m4);
2327 DFPINST_CHECK(regs);
2328
2329 /* Initialise the context for long DFP */
2330 decContextDefault(&set, DEC_INIT_DECIMAL64);
2331 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2332
2333 /* Load 64-bit unsigned value from r2 register */
2334 n2 = regs->GR_G(r2);
2335
2336 /* Convert unsigned binary integer to long DFP format */
2337 dfp_number_from_u64(&d1, n2, &set);
2338 decimal64FromNumber(&x1, &d1, &set);
2339
2340 /* Check for exception condition */
2341 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
2342
2343 /* Load result into FP register r1 */
2344 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
2345
2346 } /* end DEF_INST(convert_u64_to_dfp_long_reg) */
2347 #endif /*defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)*/ /*810*/
2348
2349
2350 /*-------------------------------------------------------------------*/
2351 /* B3FB CXSTR - Convert from signed BCD (128-bit to DFP ext) [RRE] */
2352 /*-------------------------------------------------------------------*/
DEF_INST(convert_sbcd128_to_dfp_ext_reg)2353 DEF_INST(convert_sbcd128_to_dfp_ext_reg)
2354 {
2355 int r1, r2; /* Values of R fields */
2356 decimal128 x1; /* Extended DFP values */
2357 decNumber dwork, *dp; /* Working decimal numbers */
2358 decContext set; /* Working context */
2359 BYTE pwork[16]; /* 31-digit packed work area */
2360 int32_t scale = 0; /* Scaling factor */
2361
2362 RRE(inst, regs, r1, r2);
2363 DFPINST_CHECK(regs);
2364 DFPREGPAIR_CHECK(r1, regs);
2365 ODD_CHECK(r2, regs);
2366
2367 /* Initialise the context for extended DFP */
2368 decContextDefault(&set, DEC_INIT_DECIMAL128);
2369
2370 /* Store general register pair in work area */
2371 STORE_DW(pwork, regs->GR_G(r2));
2372 STORE_DW(pwork+8, regs->GR_G(r2+1));
2373
2374 /* Convert signed BCD to internal number format */
2375 dp = decPackedToNumber(pwork, sizeof(pwork), &scale, &dwork);
2376
2377 /* Data exception if digits or sign was invalid */
2378 if (dp == NULL)
2379 {
2380 regs->dxc = DXC_DECIMAL;
2381 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2382 }
2383
2384 /* Convert internal number to DFP extended format */
2385 decimal128FromNumber(&x1, &dwork, &set);
2386
2387 /* Load result into FP register r1 */
2388 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
2389
2390 } /* end DEF_INST(convert_sbcd128_to_dfp_ext_reg) */
2391
2392
2393 /*-------------------------------------------------------------------*/
2394 /* B3F3 CDSTR - Convert from signed BCD (64-bit to DFP long) [RRE] */
2395 /*-------------------------------------------------------------------*/
DEF_INST(convert_sbcd64_to_dfp_long_reg)2396 DEF_INST(convert_sbcd64_to_dfp_long_reg)
2397 {
2398 int r1, r2; /* Values of R fields */
2399 decimal64 x1; /* Long DFP values */
2400 decNumber dwork, *dp; /* Working decimal numbers */
2401 decContext set; /* Working context */
2402 BYTE pwork[8]; /* 15-digit packed work area */
2403 int32_t scale = 0; /* Scaling factor */
2404
2405 RRE(inst, regs, r1, r2);
2406 DFPINST_CHECK(regs);
2407
2408 /* Initialise the context for long DFP */
2409 decContextDefault(&set, DEC_INIT_DECIMAL64);
2410
2411 /* Store general register in work area */
2412 STORE_DW(pwork, regs->GR_G(r2));
2413
2414 /* Convert signed BCD to internal number format */
2415 dp = decPackedToNumber(pwork, sizeof(pwork), &scale, &dwork);
2416
2417 /* Data exception if digits or sign was invalid */
2418 if (dp == NULL)
2419 {
2420 regs->dxc = DXC_DECIMAL;
2421 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2422 }
2423
2424 /* Convert internal number to DFP long format */
2425 decimal64FromNumber(&x1, &dwork, &set);
2426
2427 /* Load result into FP register r1 */
2428 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
2429
2430 } /* end DEF_INST(convert_sbcd64_to_dfp_long_reg) */
2431
2432
2433 /*-------------------------------------------------------------------*/
2434 /* B3FA CXUTR - Convert from unsigned BCD (128-bit to DFP ext) [RRE] */
2435 /*-------------------------------------------------------------------*/
DEF_INST(convert_ubcd128_to_dfp_ext_reg)2436 DEF_INST(convert_ubcd128_to_dfp_ext_reg)
2437 {
2438 unsigned i; /* Array subscript */
2439 int r1, r2; /* Values of R fields */
2440 decimal128 x1; /* Extended DFP values */
2441 decNumber dwork, *dp; /* Working decimal numbers */
2442 decContext set; /* Working context */
2443 BYTE pwork[17]; /* 33-digit packed work area */
2444 int32_t scale = 0; /* Scaling factor */
2445
2446 RRE(inst, regs, r1, r2);
2447 DFPINST_CHECK(regs);
2448 DFPREGPAIR_CHECK(r1, regs);
2449 ODD_CHECK(r2, regs);
2450
2451 /* Initialise the context for extended DFP */
2452 decContextDefault(&set, DEC_INIT_DECIMAL128);
2453
2454 /* Store general register pair in work area */
2455 pwork[0] = 0;
2456 STORE_DW(pwork+1, regs->GR_G(r2));
2457 STORE_DW(pwork+9, regs->GR_G(r2+1));
2458
2459 /* Convert unsigned BCD to signed BCD */
2460 for (i = 0; i < sizeof(pwork)-1; i++)
2461 pwork[i] = ((pwork[i] & 0x0F) << 4) | (pwork[i+1] >> 4);
2462 pwork[i] = ((pwork[i] & 0x0F) << 4) | 0x0F;
2463
2464 /* Convert signed BCD to internal number format */
2465 dp = decPackedToNumber(pwork, sizeof(pwork), &scale, &dwork);
2466
2467 /* Data exception if digits invalid */
2468 if (dp == NULL)
2469 {
2470 regs->dxc = DXC_DECIMAL;
2471 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2472 }
2473
2474 /* Convert internal number to DFP extended format */
2475 decimal128FromNumber(&x1, &dwork, &set);
2476
2477 /* Load result into FP register r1 */
2478 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
2479
2480 } /* end DEF_INST(convert_ubcd128_to_dfp_ext_reg) */
2481
2482
2483 /*-------------------------------------------------------------------*/
2484 /* B3F2 CDUTR - Convert from unsigned BCD (64-bit to DFP long) [RRE] */
2485 /*-------------------------------------------------------------------*/
DEF_INST(convert_ubcd64_to_dfp_long_reg)2486 DEF_INST(convert_ubcd64_to_dfp_long_reg)
2487 {
2488 unsigned i; /* Array subscript */
2489 int r1, r2; /* Values of R fields */
2490 decimal64 x1; /* Long DFP values */
2491 decNumber dwork, *dp; /* Working decimal numbers */
2492 decContext set; /* Working context */
2493 BYTE pwork[9]; /* 17-digit packed work area */
2494 int32_t scale = 0; /* Scaling factor */
2495
2496 RRE(inst, regs, r1, r2);
2497 DFPINST_CHECK(regs);
2498
2499 /* Initialise the context for long DFP */
2500 decContextDefault(&set, DEC_INIT_DECIMAL64);
2501
2502 /* Store general register in work area */
2503 pwork[0] = 0;
2504 STORE_DW(pwork+1, regs->GR_G(r2));
2505
2506 /* Convert unsigned BCD to signed BCD */
2507 for (i = 0; i < sizeof(pwork)-1; i++)
2508 pwork[i] = ((pwork[i] & 0x0F) << 4) | (pwork[i+1] >> 4);
2509 pwork[i] = ((pwork[i] & 0x0F) << 4) | 0x0F;
2510
2511 /* Convert signed BCD to internal number format */
2512 dp = decPackedToNumber(pwork, sizeof(pwork), &scale, &dwork);
2513
2514 /* Data exception if digits or sign was invalid */
2515 if (dp == NULL)
2516 {
2517 regs->dxc = DXC_DECIMAL;
2518 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2519 }
2520
2521 /* Convert internal number to DFP long format */
2522 decimal64FromNumber(&x1, &dwork, &set);
2523
2524 /* Load result into FP register r1 */
2525 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
2526
2527 } /* end DEF_INST(convert_ubcd64_to_dfp_long_reg) */
2528
2529
2530 #if defined(FEATURE_DFP_ZONED_CONVERSION_FACILITY) /*912*/
2531 /*-------------------------------------------------------------------*/
2532 /* EDAB CXZT - Convert from zoned to DFP Extended [RSL] */
2533 /*-------------------------------------------------------------------*/
DEF_INST(convert_zoned_to_dfp_ext)2534 DEF_INST(convert_zoned_to_dfp_ext) /*912*/
2535 {
2536 int rc; /* Return code */
2537 int r1, m3; /* Values of R and M fields */
2538 int l2; /* Operand length minus 1 */
2539 int b2; /* Base of effective addr */
2540 VADR effective_addr2; /* Effective address */
2541 decimal128 x1; /* Extended DFP value */
2542 decNumber d; /* Working decimal number */
2543 decContext set; /* Working context */
2544 char zoned[CXZT_MAXLEN]; /* Zoned decimal operand */
2545
2546 RSL_RM(inst, regs, r1, l2, b2, effective_addr2, m3);
2547 DFPINST_CHECK(regs);
2548 DFPREGPAIR_CHECK(r1, regs);
2549
2550 /* Program check if operand length exceeds maximum */
2551 if (l2 > CXZT_MAXLEN-1)
2552 {
2553 ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
2554 }
2555
2556 /* Initialise the context for extended DFP */
2557 decContextDefault(&set, DEC_INIT_DECIMAL128);
2558
2559 /* Fetch the zoned decimal operand into the work area */
2560 ARCH_DEP(vfetchc) (zoned, l2, effective_addr2, b2, regs);
2561
2562 /* Convert zoned decimal to decimal number structure */
2563 rc = dfp_number_from_zoned(&d, zoned, l2, m3, &set);
2564
2565 /* Program check if data exception is indicated */
2566 if (rc != 0)
2567 {
2568 regs->dxc = DXC_DECIMAL;
2569 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2570 }
2571
2572 /* Convert decimal number to extended DFP format */
2573 decimal128FromNumber(&x1, &d, &set);
2574
2575 /* Load result into FP register r1 */
2576 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
2577
2578 } /* end DEF_INST(convert_zoned_to_dfp_ext) */
2579
2580
2581 /*-------------------------------------------------------------------*/
2582 /* EDAA CDZT - Convert from zoned to DFP Long [RSL] */
2583 /*-------------------------------------------------------------------*/
DEF_INST(convert_zoned_to_dfp_long)2584 DEF_INST(convert_zoned_to_dfp_long) /*912*/
2585 {
2586 int rc; /* Return code */
2587 int r1, m3; /* Values of R and M fields */
2588 int l2; /* Operand length minus 1 */
2589 int b2; /* Base of effective addr */
2590 VADR effective_addr2; /* Effective address */
2591 decimal64 x1; /* Long DFP value */
2592 decNumber d; /* Working decimal number */
2593 decContext set; /* Working context */
2594 char zoned[CDZT_MAXLEN]; /* Zoned decimal operand */
2595
2596 RSL_RM(inst, regs, r1, l2, b2, effective_addr2, m3);
2597 DFPINST_CHECK(regs);
2598
2599 /* Program check if operand length exceeds maximum */
2600 if (l2 > CDZT_MAXLEN-1)
2601 {
2602 ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
2603 }
2604
2605 /* Initialise the context for long DFP */
2606 decContextDefault(&set, DEC_INIT_DECIMAL64);
2607
2608 /* Fetch the zoned decimal operand into the work area */
2609 ARCH_DEP(vfetchc) (zoned, l2, effective_addr2, b2, regs);
2610
2611 /* Convert zoned decimal to decimal number structure */
2612 rc = dfp_number_from_zoned(&d, zoned, l2, m3, &set);
2613
2614 /* Program check if data exception is indicated */
2615 if (rc != 0)
2616 {
2617 regs->dxc = DXC_DECIMAL;
2618 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2619 }
2620
2621 /* Convert decimal number to long DFP format */
2622 decimal64FromNumber(&x1, &d, &set);
2623
2624 /* Load result into FP register r1 */
2625 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
2626
2627 } /* end DEF_INST(convert_zoned_to_dfp_long) */
2628 #endif /*defined(FEATURE_DFP_ZONED_CONVERSION_FACILITY)*/ /*912*/
2629
2630
2631 #if defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY) /*810*/
2632 /*-------------------------------------------------------------------*/
2633 /* B949 CFXTR - Convert from DFP Extended Register to fixed 32 [RRF] */
2634 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_ext_to_fix32_reg)2635 DEF_INST(convert_dfp_ext_to_fix32_reg)
2636 {
2637 int r1, r2; /* Values of R fields */
2638 int m3, m4; /* Values of M fields */
2639 S32 n1; /* Result value */
2640 decimal128 x2; /* Extended DFP value */
2641 decNumber d2; /* Working decimal number */
2642 decContext set; /* Working context */
2643 BYTE dxc; /* Data exception code */
2644
2645 RRF_MM(inst, regs, r1, r2, m3, m4);
2646 DFPINST_CHECK(regs);
2647 DFPREGPAIR_CHECK(r2, regs);
2648
2649 /* Initialise the context for extended DFP */
2650 decContextDefault(&set, DEC_INIT_DECIMAL128);
2651 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2652
2653 /* Load extended DFP value from FP register r2 */
2654 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
2655 decimal128ToNumber(&x2, &d2);
2656
2657 /* Convert decimal number to 32-bit binary integer */
2658 n1 = dfp_number_to_fix32(&d2, &set);
2659
2660 /* Check for exception condition */
2661 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
2662
2663 /* Load result into general register r1 */
2664 regs->GR_L(r1) = n1;
2665
2666 /* Set condition code */
2667 regs->psw.cc = (set.status & DEC_IEEE_854_Invalid_operation) ? 3 :
2668 decNumberIsZero(&d2) ? 0 :
2669 decNumberIsNegative(&d2) ? 1 : 2;
2670
2671 /* Raise data exception if error occurred */
2672 if (dxc != 0)
2673 {
2674 regs->dxc = dxc;
2675 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2676 }
2677
2678 } /* end DEF_INST(convert_dfp_ext_to_fix32_reg) */
2679
2680
2681 /*-------------------------------------------------------------------*/
2682 /* B941 CFDTR - Convert from DFP Long Register to fixed 32 [RRF] */
2683 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_long_to_fix32_reg)2684 DEF_INST(convert_dfp_long_to_fix32_reg)
2685 {
2686 int r1, r2; /* Values of R fields */
2687 int m3, m4; /* Values of M fields */
2688 S32 n1; /* Result value */
2689 decimal64 x2; /* Long DFP value */
2690 decNumber d2; /* Working decimal number */
2691 decContext set; /* Working context */
2692 BYTE dxc; /* Data exception code */
2693
2694 RRF_MM(inst, regs, r1, r2, m3, m4);
2695 DFPINST_CHECK(regs);
2696
2697 /* Initialise the context for long DFP */
2698 decContextDefault(&set, DEC_INIT_DECIMAL64);
2699 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2700
2701 /* Load long DFP value from FP register r2 */
2702 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
2703 decimal64ToNumber(&x2, &d2);
2704
2705 /* Convert decimal number to 32-bit binary integer */
2706 n1 = dfp_number_to_fix32(&d2, &set);
2707
2708 /* Check for exception condition */
2709 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
2710
2711 /* Load result into general register r1 */
2712 regs->GR_L(r1) = n1;
2713
2714 /* Set condition code */
2715 regs->psw.cc = (set.status & DEC_IEEE_854_Invalid_operation) ? 3 :
2716 decNumberIsZero(&d2) ? 0 :
2717 decNumberIsNegative(&d2) ? 1 : 2;
2718
2719 /* Raise data exception if error occurred */
2720 if (dxc != 0)
2721 {
2722 regs->dxc = dxc;
2723 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2724 }
2725
2726 } /* end DEF_INST(convert_dfp_long_to_fix32_reg) */
2727
2728
2729 /*-------------------------------------------------------------------*/
2730 /* B94B CLFXTR - Convert from DFP Ext Register to unsigned 32 [RRF] */
2731 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_ext_to_u32_reg)2732 DEF_INST(convert_dfp_ext_to_u32_reg)
2733 {
2734 int r1, r2; /* Values of R fields */
2735 int m3, m4; /* Values of M fields */
2736 U32 n1; /* Result value */
2737 decimal128 x2; /* Extended DFP value */
2738 decNumber d2; /* Working decimal number */
2739 decContext set; /* Working context */
2740 BYTE dxc; /* Data exception code */
2741
2742 RRF_MM(inst, regs, r1, r2, m3, m4);
2743 DFPINST_CHECK(regs);
2744 DFPREGPAIR_CHECK(r2, regs);
2745
2746 /* Initialise the context for extended DFP */
2747 decContextDefault(&set, DEC_INIT_DECIMAL128);
2748 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2749
2750 /* Load extended DFP value from FP register r2 */
2751 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
2752 decimal128ToNumber(&x2, &d2);
2753
2754 /* Convert decimal number to 32-bit unsigned integer */
2755 n1 = dfp_number_to_u32(&d2, &set);
2756
2757 /* Check for exception condition */
2758 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
2759
2760 /* Load result into general register r1 */
2761 regs->GR_L(r1) = n1;
2762
2763 /* Set condition code */
2764 regs->psw.cc = (set.status & DEC_IEEE_854_Invalid_operation) ? 3 :
2765 decNumberIsZero(&d2) ? 0 :
2766 decNumberIsNegative(&d2) ? 1 : 2;
2767
2768 /* Raise data exception if error occurred */
2769 if (dxc != 0)
2770 {
2771 regs->dxc = dxc;
2772 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2773 }
2774
2775 } /* end DEF_INST(convert_dfp_ext_to_u32_reg) */
2776
2777
2778 /*-------------------------------------------------------------------*/
2779 /* B943 CLFDTR - Convert from DFP Long Register to unsigned 32 [RRF] */
2780 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_long_to_u32_reg)2781 DEF_INST(convert_dfp_long_to_u32_reg)
2782 {
2783 int r1, r2; /* Values of R fields */
2784 int m3, m4; /* Values of M fields */
2785 U32 n1; /* Result value */
2786 decimal64 x2; /* Long DFP value */
2787 decNumber d2; /* Working decimal number */
2788 decContext set; /* Working context */
2789 BYTE dxc; /* Data exception code */
2790
2791 RRF_MM(inst, regs, r1, r2, m3, m4);
2792 DFPINST_CHECK(regs);
2793
2794 /* Initialise the context for long DFP */
2795 decContextDefault(&set, DEC_INIT_DECIMAL64);
2796 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2797
2798 /* Load long DFP value from FP register r2 */
2799 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
2800 decimal64ToNumber(&x2, &d2);
2801
2802 /* Convert decimal number to 32-bit unsigned integer */
2803 n1 = dfp_number_to_u32(&d2, &set);
2804
2805 /* Check for exception condition */
2806 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
2807
2808 /* Load result into general register r1 */
2809 regs->GR_L(r1) = n1;
2810
2811 /* Set condition code */
2812 regs->psw.cc = (set.status & DEC_IEEE_854_Invalid_operation) ? 3 :
2813 decNumberIsZero(&d2) ? 0 :
2814 decNumberIsNegative(&d2) ? 1 : 2;
2815
2816 /* Raise data exception if error occurred */
2817 if (dxc != 0)
2818 {
2819 regs->dxc = dxc;
2820 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2821 }
2822
2823 } /* end DEF_INST(convert_dfp_long_to_u32_reg) */
2824 #endif /*defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)*/ /*810*/
2825
2826
2827 /*-------------------------------------------------------------------*/
2828 /* B3E9 CGXTR - Convert from DFP Extended Register to fixed 64 [RRF] */
2829 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_ext_to_fix64_reg)2830 DEF_INST(convert_dfp_ext_to_fix64_reg)
2831 {
2832 int r1, r2; /* Values of R fields */
2833 int m3; /* Values of M fields */
2834 S64 n1; /* Result value */
2835 decimal128 x2; /* Extended DFP value */
2836 decNumber d2; /* Working decimal number */
2837 decContext set; /* Working context */
2838 BYTE dxc; /* Data exception code */
2839
2840 RRF_M(inst, regs, r1, r2, m3);
2841 DFPINST_CHECK(regs);
2842 DFPREGPAIR_CHECK(r2, regs);
2843
2844 /* Initialise the context for extended DFP */
2845 decContextDefault(&set, DEC_INIT_DECIMAL128);
2846 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2847
2848 /* Load extended DFP value from FP register r2 */
2849 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
2850 decimal128ToNumber(&x2, &d2);
2851
2852 /* Convert decimal number to 64-bit binary integer */
2853 n1 = dfp_number_to_fix64(&d2, &set);
2854
2855 /* Check for exception condition */
2856 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
2857
2858 /* Load result into general register r1 */
2859 regs->GR_G(r1) = n1;
2860
2861 /* Set condition code */
2862 regs->psw.cc = (set.status & DEC_IEEE_854_Invalid_operation) ? 3 :
2863 decNumberIsZero(&d2) ? 0 :
2864 decNumberIsNegative(&d2) ? 1 : 2;
2865
2866 /* Raise data exception if error occurred */
2867 if (dxc != 0)
2868 {
2869 regs->dxc = dxc;
2870 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2871 }
2872
2873 } /* end DEF_INST(convert_dfp_ext_to_fix64_reg) */
2874
2875
2876 /*-------------------------------------------------------------------*/
2877 /* B3E1 CGDTR - Convert from DFP Long Register to fixed 64 [RRF] */
2878 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_long_to_fix64_reg)2879 DEF_INST(convert_dfp_long_to_fix64_reg)
2880 {
2881 int r1, r2; /* Values of R fields */
2882 int m3; /* Values of M fields */
2883 S64 n1; /* Result value */
2884 decimal64 x2; /* Long DFP value */
2885 decNumber d2; /* Working decimal number */
2886 decContext set; /* Working context */
2887 BYTE dxc; /* Data exception code */
2888
2889 RRF_M(inst, regs, r1, r2, m3);
2890 DFPINST_CHECK(regs);
2891
2892 /* Initialise the context for long DFP */
2893 decContextDefault(&set, DEC_INIT_DECIMAL64);
2894 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2895
2896 /* Load long DFP value from FP register r2 */
2897 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
2898 decimal64ToNumber(&x2, &d2);
2899
2900 /* Convert decimal number to 64-bit binary integer */
2901 n1 = dfp_number_to_fix64(&d2, &set);
2902
2903 /* Check for exception condition */
2904 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
2905
2906 /* Load result into general register r1 */
2907 regs->GR_G(r1) = n1;
2908
2909 /* Set condition code */
2910 regs->psw.cc = (set.status & DEC_IEEE_854_Invalid_operation) ? 3 :
2911 decNumberIsZero(&d2) ? 0 :
2912 decNumberIsNegative(&d2) ? 1 : 2;
2913
2914 /* Raise data exception if error occurred */
2915 if (dxc != 0)
2916 {
2917 regs->dxc = dxc;
2918 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2919 }
2920
2921 } /* end DEF_INST(convert_dfp_long_to_fix64_reg) */
2922
2923
2924 #if defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY) /*810*/
2925 /*-------------------------------------------------------------------*/
2926 /* B94A CLGXTR - Convert from DFP Ext Register to unsigned 64 [RRF] */
2927 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_ext_to_u64_reg)2928 DEF_INST(convert_dfp_ext_to_u64_reg)
2929 {
2930 int r1, r2; /* Values of R fields */
2931 int m3, m4; /* Values of M fields */
2932 U64 n1; /* Result value */
2933 decimal128 x2; /* Extended DFP value */
2934 decNumber d2; /* Working decimal number */
2935 decContext set; /* Working context */
2936 BYTE dxc; /* Data exception code */
2937
2938 RRF_MM(inst, regs, r1, r2, m3, m4);
2939 DFPINST_CHECK(regs);
2940 DFPREGPAIR_CHECK(r2, regs);
2941
2942 /* Initialise the context for extended DFP */
2943 decContextDefault(&set, DEC_INIT_DECIMAL128);
2944 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2945
2946 /* Load extended DFP value from FP register r2 */
2947 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
2948 decimal128ToNumber(&x2, &d2);
2949
2950 /* Convert decimal number to 64-bit unsigned integer */
2951 n1 = dfp_number_to_u64(&d2, &set);
2952
2953 /* Check for exception condition */
2954 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
2955
2956 /* Load result into general register r1 */
2957 regs->GR_G(r1) = n1;
2958
2959 /* Set condition code */
2960 regs->psw.cc = (set.status & DEC_IEEE_854_Invalid_operation) ? 3 :
2961 decNumberIsZero(&d2) ? 0 :
2962 decNumberIsNegative(&d2) ? 1 : 2;
2963
2964 /* Raise data exception if error occurred */
2965 if (dxc != 0)
2966 {
2967 regs->dxc = dxc;
2968 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
2969 }
2970
2971 } /* end DEF_INST(convert_dfp_ext_to_u64_reg) */
2972
2973
2974 /*-------------------------------------------------------------------*/
2975 /* B942 CLGDTR - Convert from DFP Long Register to unsigned 64 [RRF] */
2976 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_long_to_u64_reg)2977 DEF_INST(convert_dfp_long_to_u64_reg)
2978 {
2979 int r1, r2; /* Values of R fields */
2980 int m3, m4; /* Values of M fields */
2981 U64 n1; /* Result value */
2982 decimal64 x2; /* Long DFP value */
2983 decNumber d2; /* Working decimal number */
2984 decContext set; /* Working context */
2985 BYTE dxc; /* Data exception code */
2986
2987 RRF_MM(inst, regs, r1, r2, m3, m4);
2988 DFPINST_CHECK(regs);
2989
2990 /* Initialise the context for long DFP */
2991 decContextDefault(&set, DEC_INIT_DECIMAL64);
2992 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
2993
2994 /* Load long DFP value from FP register r2 */
2995 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
2996 decimal64ToNumber(&x2, &d2);
2997
2998 /* Convert decimal number to 64-bit unsigned integer */
2999 n1 = dfp_number_to_u64(&d2, &set);
3000
3001 /* Check for exception condition */
3002 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
3003
3004 /* Load result into general register r1 */
3005 regs->GR_G(r1) = n1;
3006
3007 /* Set condition code */
3008 regs->psw.cc = (set.status & DEC_IEEE_854_Invalid_operation) ? 3 :
3009 decNumberIsZero(&d2) ? 0 :
3010 decNumberIsNegative(&d2) ? 1 : 2;
3011
3012 /* Raise data exception if error occurred */
3013 if (dxc != 0)
3014 {
3015 regs->dxc = dxc;
3016 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
3017 }
3018
3019 } /* end DEF_INST(convert_dfp_long_to_u64_reg) */
3020 #endif /*defined(FEATURE_FLOATING_POINT_EXTENSION_FACILITY)*/ /*810*/
3021
3022
3023 /*-------------------------------------------------------------------*/
3024 /* B3EB CSXTR - Convert to signed BCD (DFP ext to 128-bit) [RRF] */
3025 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_ext_to_sbcd128_reg)3026 DEF_INST(convert_dfp_ext_to_sbcd128_reg)
3027 {
3028 int r1, r2; /* Values of R fields */
3029 int m4; /* Values of M fields */
3030 decimal128 x2; /* Extended DFP values */
3031 decNumber dwork; /* Working decimal number */
3032 decContext set; /* Working context */
3033 int32_t scale; /* Scaling factor */
3034 BYTE pwork[17]; /* 33-digit packed work area */
3035
3036 RRF_M4(inst, regs, r1, r2, m4);
3037 DFPINST_CHECK(regs);
3038 DFPREGPAIR_CHECK(r2, regs);
3039 ODD_CHECK(r1, regs);
3040
3041 /* Initialise the context for extended DFP */
3042 decContextDefault(&set, DEC_INIT_DECIMAL128);
3043
3044 /* Load DFP extended number from FP register r2 */
3045 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
3046 decimal128ToNumber(&x2, &dwork);
3047
3048 /* If NaN or Inf then use coefficient only */
3049 if (decNumberIsNaN(&dwork) || (decNumberIsInfinite(&dwork)))
3050 {
3051 dfp128_clear_cf_and_bxcf(&x2);
3052 decimal128ToNumber(&x2, &dwork);
3053 }
3054
3055 /* Convert number to signed BCD in work area */
3056 decPackedFromNumber(pwork, sizeof(pwork), &scale, &dwork);
3057
3058 /* Make the plus-sign X'F' if m4 bit 3 is one */
3059 if ((m4 & 0x01) && !decNumberIsNegative(&dwork))
3060 pwork[sizeof(pwork)-1] |= 0x0F;
3061
3062 /* Load general register pair r1 and r1+1 from
3063 rightmost 31 packed decimal digits of work area */
3064 FETCH_DW(regs->GR_G(r1), pwork+sizeof(pwork)-16);
3065 FETCH_DW(regs->GR_G(r1+1), pwork+sizeof(pwork)-8);
3066
3067 } /* end DEF_INST(convert_dfp_ext_to_sbcd128_reg) */
3068
3069
3070 /*-------------------------------------------------------------------*/
3071 /* B3E3 CSDTR - Convert to signed BCD (DFP long to 64-bit) [RRF] */
3072 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_long_to_sbcd64_reg)3073 DEF_INST(convert_dfp_long_to_sbcd64_reg)
3074 {
3075 int r1, r2; /* Values of R fields */
3076 int m4; /* Values of M fields */
3077 decimal64 x2; /* Long DFP values */
3078 decNumber dwork; /* Working decimal number */
3079 decContext set; /* Working context */
3080 int32_t scale; /* Scaling factor */
3081 BYTE pwork[9]; /* 17-digit packed work area */
3082
3083 RRF_M4(inst, regs, r1, r2, m4);
3084 DFPINST_CHECK(regs);
3085
3086 /* Initialise the context for long DFP */
3087 decContextDefault(&set, DEC_INIT_DECIMAL64);
3088
3089 /* Load DFP long number from FP register r2 */
3090 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
3091 decimal64ToNumber(&x2, &dwork);
3092
3093 /* If NaN or Inf then use coefficient only */
3094 if (decNumberIsNaN(&dwork) || (decNumberIsInfinite(&dwork)))
3095 {
3096 dfp64_clear_cf_and_bxcf(&x2);
3097 decimal64ToNumber(&x2, &dwork);
3098 }
3099
3100 /* Convert number to signed BCD in work area */
3101 decPackedFromNumber(pwork, sizeof(pwork), &scale, &dwork);
3102
3103 /* Make the plus-sign X'F' if m4 bit 3 is one */
3104 if ((m4 & 0x01) && !decNumberIsNegative(&dwork))
3105 pwork[sizeof(pwork)-1] |= 0x0F;
3106
3107 /* Load general register r1 from rightmost
3108 15 packed decimal digits of work area */
3109 FETCH_DW(regs->GR_G(r1), pwork+sizeof(pwork)-8);
3110
3111 } /* end DEF_INST(convert_dfp_long_to_sbcd64_reg) */
3112
3113
3114 /*-------------------------------------------------------------------*/
3115 /* B3EA CUXTR - Convert to unsigned BCD (DFP ext to 128-bit) [RRE] */
3116 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_ext_to_ubcd128_reg)3117 DEF_INST(convert_dfp_ext_to_ubcd128_reg)
3118 {
3119 int i; /* Array subscript */
3120 int r1, r2; /* Values of R fields */
3121 decimal128 x2; /* Extended DFP values */
3122 decNumber dwork; /* Working decimal number */
3123 decContext set; /* Working context */
3124 int32_t scale; /* Scaling factor */
3125 BYTE pwork[17]; /* 33-digit packed work area */
3126
3127 RRE(inst, regs, r1, r2);
3128 DFPINST_CHECK(regs);
3129 DFPREGPAIR_CHECK(r2, regs);
3130 ODD_CHECK(r1, regs);
3131
3132 /* Initialise the context for extended DFP */
3133 decContextDefault(&set, DEC_INIT_DECIMAL128);
3134
3135 /* Load DFP extended number from FP register r2 */
3136 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
3137 decimal128ToNumber(&x2, &dwork);
3138
3139 /* If NaN or Inf then use coefficient only */
3140 if (decNumberIsNaN(&dwork) || (decNumberIsInfinite(&dwork)))
3141 {
3142 dfp128_clear_cf_and_bxcf(&x2);
3143 decimal128ToNumber(&x2, &dwork);
3144 }
3145
3146 /* Convert number to signed BCD in work area */
3147 decPackedFromNumber(pwork, sizeof(pwork), &scale, &dwork);
3148
3149 /* Convert signed BCD to unsigned BCD */
3150 for (i = sizeof(pwork)-1; i > 0; i--)
3151 pwork[i] = (pwork[i] >> 4) | ((pwork[i-1] & 0x0F) << 4);
3152
3153 /* Load general register pair r1 and r1+1 from
3154 rightmost 32 packed decimal digits of work area */
3155 FETCH_DW(regs->GR_G(r1), pwork+sizeof(pwork)-16);
3156 FETCH_DW(regs->GR_G(r1+1), pwork+sizeof(pwork)-8);
3157
3158 } /* end DEF_INST(convert_dfp_ext_to_ubcd128_reg) */
3159
3160
3161 /*-------------------------------------------------------------------*/
3162 /* B3E2 CUDTR - Convert to unsigned BCD (DFP long to 64-bit) [RRE] */
3163 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_long_to_ubcd64_reg)3164 DEF_INST(convert_dfp_long_to_ubcd64_reg)
3165 {
3166 int i; /* Array subscript */
3167 int r1, r2; /* Values of R fields */
3168 decimal64 x2; /* Long DFP values */
3169 decNumber dwork; /* Working decimal number */
3170 decContext set; /* Working context */
3171 int32_t scale; /* Scaling factor */
3172 BYTE pwork[9]; /* 17-digit packed work area */
3173
3174 RRE(inst, regs, r1, r2);
3175 DFPINST_CHECK(regs);
3176
3177 /* Initialise the context for long DFP */
3178 decContextDefault(&set, DEC_INIT_DECIMAL64);
3179
3180 /* Load DFP long number from FP register r2 */
3181 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
3182 decimal64ToNumber(&x2, &dwork);
3183
3184 /* If NaN or Inf then use coefficient only */
3185 if (decNumberIsNaN(&dwork) || (decNumberIsInfinite(&dwork)))
3186 {
3187 dfp64_clear_cf_and_bxcf(&x2);
3188 decimal64ToNumber(&x2, &dwork);
3189 }
3190
3191 /* Convert number to signed BCD in work area */
3192 decPackedFromNumber(pwork, sizeof(pwork), &scale, &dwork);
3193
3194 /* Convert signed BCD to unsigned BCD */
3195 for (i = sizeof(pwork)-1; i > 0; i--)
3196 pwork[i] = (pwork[i] >> 4) | ((pwork[i-1] & 0x0F) << 4);
3197
3198 /* Load general register r1 from rightmost
3199 16 packed decimal digits of work area */
3200 FETCH_DW(regs->GR_G(r1), pwork+sizeof(pwork)-8);
3201
3202 } /* end DEF_INST(convert_dfp_long_to_ubcd64_reg) */
3203
3204
3205 #if defined(FEATURE_DFP_ZONED_CONVERSION_FACILITY) /*912*/
3206 /*-------------------------------------------------------------------*/
3207 /* EDA9 CZXT - Convert to zoned from DFP Extended [RSL] */
3208 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_ext_to_zoned)3209 DEF_INST(convert_dfp_ext_to_zoned) /*912*/
3210 {
3211 int r1, m3; /* Values of R and M fields */
3212 int l2; /* Operand length minus 1 */
3213 int b2; /* Base of effective addr */
3214 VADR effective_addr2; /* Effective address */
3215 decimal128 x1; /* Extended DFP value */
3216 decNumber dwork, dcoeff; /* Working decimal numbers */
3217 decContext set; /* Working context */
3218 int cc; /* Condition code */
3219 char zoned[CZXT_MAXLEN]; /* Zoned decimal result */
3220
3221 RSL_RM(inst, regs, r1, l2, b2, effective_addr2, m3);
3222 DFPINST_CHECK(regs);
3223 DFPREGPAIR_CHECK(r1, regs);
3224
3225 /* Program check if operand length exceeds 34 */
3226 if (l2 > CZXT_MAXLEN-1)
3227 {
3228 ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
3229 }
3230
3231 /* Initialise the context for extended DFP */
3232 decContextDefault(&set, DEC_INIT_DECIMAL128);
3233
3234 /* Load DFP extended number from FP register r1 */
3235 ARCH_DEP(dfp_reg_to_decimal128)(r1, &x1, regs);
3236 decimal128ToNumber(&x1, &dwork);
3237
3238 /* Extract coefficient only for Inf and NaN */
3239 if (decNumberIsNaN(&dwork) || (decNumberIsInfinite(&dwork)))
3240 {
3241 dfp128_clear_cf_and_bxcf(&x1);
3242 decimal128ToNumber(&x1, &dcoeff);
3243 }
3244
3245 /* Convert number to zoned decimal and set condition code */
3246 cc = dfp_number_to_zoned(&dwork, &dcoeff, zoned, l2, m3, &set);
3247
3248 /* Store the zoned decimal result at the operand location */
3249 ARCH_DEP(vstorec) (zoned, l2, effective_addr2, b2, regs);
3250
3251 /* Set the condition code in the PSW */
3252 regs->psw.cc = cc;
3253
3254 } /* end DEF_INST(convert_dfp_ext_to_zoned) */
3255
3256
3257 /*-------------------------------------------------------------------*/
3258 /* EDA8 CZDT - Convert to zoned from DFP Long [RSL] */
3259 /*-------------------------------------------------------------------*/
DEF_INST(convert_dfp_long_to_zoned)3260 DEF_INST(convert_dfp_long_to_zoned) /*912*/
3261 {
3262 int r1, m3; /* Values of R and M fields */
3263 int l2; /* Operand length minus 1 */
3264 int b2; /* Base of effective addr */
3265 VADR effective_addr2; /* Effective address */
3266 decimal64 x1; /* Long DFP value */
3267 decNumber dwork, dcoeff; /* Working decimal numbers */
3268 decContext set; /* Working context */
3269 int cc; /* Condition code */
3270 char zoned[CZDT_MAXLEN]; /* Zoned decimal result */
3271
3272 RSL_RM(inst, regs, r1, l2, b2, effective_addr2, m3);
3273 DFPINST_CHECK(regs);
3274
3275 /* Program check if operand length exceeds 16 */
3276 if (l2 > CZDT_MAXLEN-1)
3277 {
3278 ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
3279 }
3280
3281 /* Initialise the context for long DFP */
3282 decContextDefault(&set, DEC_INIT_DECIMAL64);
3283
3284 /* Load DFP long number from FP register r1 */
3285 ARCH_DEP(dfp_reg_to_decimal64)(r1, &x1, regs);
3286 decimal64ToNumber(&x1, &dwork);
3287
3288 /* Extract coefficient only for Inf and NaN */
3289 if (decNumberIsNaN(&dwork) || (decNumberIsInfinite(&dwork)))
3290 {
3291 dfp64_clear_cf_and_bxcf(&x1);
3292 decimal64ToNumber(&x1, &dcoeff);
3293 }
3294
3295 /* Convert number to zoned decimal and set condition code */
3296 cc = dfp_number_to_zoned(&dwork, &dcoeff, zoned, l2, m3, &set);
3297
3298 /* Store the zoned decimal result at the operand location */
3299 ARCH_DEP(vstorec) (zoned, l2, effective_addr2, b2, regs);
3300
3301 /* Set the condition code in the PSW */
3302 regs->psw.cc = cc;
3303
3304 } /* end DEF_INST(convert_dfp_long_to_zoned) */
3305 #endif /*defined(FEATURE_DFP_ZONED_CONVERSION_FACILITY)*/ /*912*/
3306
3307
3308 /*-------------------------------------------------------------------*/
3309 /* B3D9 DXTR - Divide DFP Extended Register [RRR] */
3310 /*-------------------------------------------------------------------*/
DEF_INST(divide_dfp_ext_reg)3311 DEF_INST(divide_dfp_ext_reg)
3312 {
3313 int r1, r2, r3; /* Values of R fields */
3314 decimal128 x1, x2, x3; /* Extended DFP values */
3315 decNumber d1, d2, d3; /* Working decimal numbers */
3316 decContext set; /* Working context */
3317 BYTE dxc; /* Data exception code */
3318
3319 RRR(inst, regs, r1, r2, r3);
3320 DFPINST_CHECK(regs);
3321 DFPREGPAIR3_CHECK(r1, r2, r3, regs);
3322
3323 /* Initialise the context for extended DFP */
3324 decContextDefault(&set, DEC_INIT_DECIMAL128);
3325 ARCH_DEP(dfp_rounding_mode)(&set, 0, regs);
3326
3327 /* Divide FP register r2 by FP register r3 */
3328 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
3329 ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs);
3330 decimal128ToNumber(&x2, &d2);
3331 decimal128ToNumber(&x3, &d3);
3332 decNumberDivide(&d1, &d2, &d3, &set);
3333 decimal128FromNumber(&x1, &d1, &set);
3334
3335 /* Check for exception condition */
3336 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
3337
3338 /* Load result into FP register r1 */
3339 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
3340
3341 /* Raise data exception if error occurred */
3342 if (dxc != 0)
3343 {
3344 regs->dxc = dxc;
3345 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
3346 }
3347
3348 } /* end DEF_INST(divide_dfp_ext_reg) */
3349
3350
3351 /*-------------------------------------------------------------------*/
3352 /* B3D1 DDTR - Divide DFP Long Register [RRR] */
3353 /*-------------------------------------------------------------------*/
DEF_INST(divide_dfp_long_reg)3354 DEF_INST(divide_dfp_long_reg)
3355 {
3356 int r1, r2, r3; /* Values of R fields */
3357 decimal64 x1, x2, x3; /* Long DFP values */
3358 decNumber d1, d2, d3; /* Working decimal numbers */
3359 decContext set; /* Working context */
3360 BYTE dxc; /* Data exception code */
3361
3362 RRR(inst, regs, r1, r2, r3);
3363 DFPINST_CHECK(regs);
3364
3365 /* Initialise the context for long DFP */
3366 decContextDefault(&set, DEC_INIT_DECIMAL64);
3367 ARCH_DEP(dfp_rounding_mode)(&set, 0, regs);
3368
3369 /* Divide FP register r2 by FP register r3 */
3370 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
3371 ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs);
3372 decimal64ToNumber(&x2, &d2);
3373 decimal64ToNumber(&x3, &d3);
3374 decNumberDivide(&d1, &d2, &d3, &set);
3375 decimal64FromNumber(&x1, &d1, &set);
3376
3377 /* Check for exception condition */
3378 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
3379
3380 /* Load result into FP register r1 */
3381 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
3382
3383 /* Raise data exception if error occurred */
3384 if (dxc != 0)
3385 {
3386 regs->dxc = dxc;
3387 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
3388 }
3389
3390 } /* end DEF_INST(divide_dfp_long_reg) */
3391
3392
3393 /*-------------------------------------------------------------------*/
3394 /* B3ED EEXTR - Extract Biased Exponent DFP Extended Register [RRE] */
3395 /*-------------------------------------------------------------------*/
DEF_INST(extract_biased_exponent_dfp_ext_to_fix64_reg)3396 DEF_INST(extract_biased_exponent_dfp_ext_to_fix64_reg)
3397 {
3398 int r1, r2; /* Values of R fields */
3399 decimal128 x2; /* Extended DFP value */
3400 decNumber d2; /* Working decimal number */
3401 decContext set; /* Working context */
3402 S64 exponent; /* Biased exponent */
3403
3404 RRE(inst, regs, r1, r2);
3405 DFPINST_CHECK(regs);
3406 DFPREGPAIR_CHECK(r2, regs);
3407
3408 /* Initialise the context for extended DFP */
3409 decContextDefault(&set, DEC_INIT_DECIMAL128);
3410
3411 /* Load DFP extended number from FP register r2 */
3412 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
3413
3414 /* Convert to internal decimal number format */
3415 decimal128ToNumber(&x2, &d2);
3416
3417 /* Calculate the biased exponent */
3418 if (decNumberIsInfinite(&d2))
3419 exponent = -1;
3420 else if (decNumberIsQNaN(&d2))
3421 exponent = -2;
3422 else if (decNumberIsSNaN(&d2))
3423 exponent = -3;
3424 else
3425 exponent = d2.exponent + DECIMAL128_Bias;
3426
3427 /* Load result into general register r1 */
3428 regs->GR(r1) = exponent;
3429
3430 } /* end DEF_INST(extract_biased_exponent_dfp_ext_to_fix64_reg) */
3431
3432
3433 /*-------------------------------------------------------------------*/
3434 /* B3E5 EEDTR - Extract Biased Exponent DFP Long Register [RRE] */
3435 /*-------------------------------------------------------------------*/
DEF_INST(extract_biased_exponent_dfp_long_to_fix64_reg)3436 DEF_INST(extract_biased_exponent_dfp_long_to_fix64_reg)
3437 {
3438 int r1, r2; /* Values of R fields */
3439 decimal64 x2; /* Long DFP value */
3440 decNumber d2; /* Working decimal number */
3441 decContext set; /* Working context */
3442 S64 exponent; /* Biased exponent */
3443
3444 RRE(inst, regs, r1, r2);
3445 DFPINST_CHECK(regs);
3446
3447 /* Initialise the context for long DFP */
3448 decContextDefault(&set, DEC_INIT_DECIMAL64);
3449
3450 /* Load DFP long number from FP register r2 */
3451 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
3452
3453 /* Convert to internal decimal number format */
3454 decimal64ToNumber(&x2, &d2);
3455
3456 /* Calculate the biased exponent */
3457 if (decNumberIsInfinite(&d2))
3458 exponent = -1;
3459 else if (decNumberIsQNaN(&d2))
3460 exponent = -2;
3461 else if (decNumberIsSNaN(&d2))
3462 exponent = -3;
3463 else
3464 exponent = d2.exponent + DECIMAL64_Bias;
3465
3466 /* Load result into general register r1 */
3467 regs->GR(r1) = exponent;
3468
3469 } /* end DEF_INST(extract_biased_exponent_dfp_long_to_fix64_reg) */
3470
3471
3472 /*-------------------------------------------------------------------*/
3473 /* B3EF ESXTR - Extract Significance DFP Extended Register [RRE] */
3474 /*-------------------------------------------------------------------*/
DEF_INST(extract_significance_dfp_ext_reg)3475 DEF_INST(extract_significance_dfp_ext_reg)
3476 {
3477 int r1, r2; /* Values of R fields */
3478 decimal128 x2; /* Extended DFP value */
3479 decNumber d2; /* Working decimal number */
3480 decContext set; /* Working context */
3481 S64 digits; /* Number of decimal digits */
3482
3483 RRE(inst, regs, r1, r2);
3484 DFPINST_CHECK(regs);
3485 DFPREGPAIR_CHECK(r2, regs);
3486
3487 /* Initialise the context for extended DFP */
3488 decContextDefault(&set, DEC_INIT_DECIMAL128);
3489
3490 /* Load DFP extended number from FP register r2 */
3491 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
3492
3493 /* Convert to internal decimal number format */
3494 decimal128ToNumber(&x2, &d2);
3495
3496 /* Calculate number of significant digits */
3497 if (decNumberIsZero(&d2))
3498 digits = 0;
3499 else if (decNumberIsInfinite(&d2))
3500 digits = -1;
3501 else if (decNumberIsQNaN(&d2))
3502 digits = -2;
3503 else if (decNumberIsSNaN(&d2))
3504 digits = -3;
3505 else
3506 digits = d2.digits;
3507
3508 /* Load result into general register r1 */
3509 regs->GR(r1) = digits;
3510
3511 } /* end DEF_INST(extract_significance_dfp_ext_reg) */
3512
3513
3514 /*-------------------------------------------------------------------*/
3515 /* B3E7 ESDTR - Extract Significance DFP Long Register [RRE] */
3516 /*-------------------------------------------------------------------*/
DEF_INST(extract_significance_dfp_long_reg)3517 DEF_INST(extract_significance_dfp_long_reg)
3518 {
3519 int r1, r2; /* Values of R fields */
3520 decimal64 x2; /* Long DFP value */
3521 decNumber d2; /* Working decimal number */
3522 decContext set; /* Working context */
3523 S64 digits; /* Number of decimal digits */
3524
3525 RRE(inst, regs, r1, r2);
3526 DFPINST_CHECK(regs);
3527
3528 /* Initialise the context for long DFP */
3529 decContextDefault(&set, DEC_INIT_DECIMAL64);
3530
3531 /* Load DFP long number from FP register r2 */
3532 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
3533
3534 /* Convert to internal decimal number format */
3535 decimal64ToNumber(&x2, &d2);
3536
3537 /* Calculate number of significant digits */
3538 if (decNumberIsZero(&d2))
3539 digits = 0;
3540 else if (decNumberIsInfinite(&d2))
3541 digits = -1;
3542 else if (decNumberIsQNaN(&d2))
3543 digits = -2;
3544 else if (decNumberIsSNaN(&d2))
3545 digits = -3;
3546 else
3547 digits = d2.digits;
3548
3549 /* Load result into general register r1 */
3550 regs->GR(r1) = digits;
3551
3552 } /* end DEF_INST(extract_significance_dfp_long_reg) */
3553
3554
3555 /*-------------------------------------------------------------------*/
3556 /* B3FE IEXTR - Insert Biased Exponent DFP Extended Register [RRF] */
3557 /*-------------------------------------------------------------------*/
DEF_INST(insert_biased_exponent_fix64_to_dfp_ext_reg)3558 DEF_INST(insert_biased_exponent_fix64_to_dfp_ext_reg)
3559 {
3560 int r1, r2, r3; /* Values of R fields */
3561 decimal128 x1, x3; /* Extended DFP values */
3562 decNumber d; /* Working decimal number */
3563 decContext set; /* Working context */
3564 S64 bexp; /* Biased exponent */
3565
3566 RRF_M(inst, regs, r1, r2, r3);
3567 DFPINST_CHECK(regs);
3568 DFPREGPAIR2_CHECK(r1, r3, regs);
3569
3570 /* Initialise the context for extended DFP */
3571 decContextDefault(&set, DEC_INIT_DECIMAL128);
3572
3573 /* Load biased exponent from general register r2 */
3574 bexp = (S64)(regs->GR(r2));
3575
3576 /* Load DFP extended number from FP register r3 */
3577 ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs);
3578
3579 /* Insert biased exponent into number */
3580 if (bexp > DECIMAL128_Ehigh || bexp == -2 || bexp <= -4)
3581 {
3582 /* Result is a QNaN with re-encoded coefficient-continuation */
3583 dfp128_clear_cf_and_bxcf(&x3);
3584 decimal128ToNumber(&x3, &d);
3585 decimal128FromNumber(&x1, &d, &set);
3586 dfp128_set_cf_and_bxcf(&x1, DFP_CFS_QNAN);
3587 }
3588 else if (bexp == -3)
3589 {
3590 /* Result is a SNaN with re-encoded coefficient-continuation */
3591 dfp128_clear_cf_and_bxcf(&x3);
3592 decimal128ToNumber(&x3, &d);
3593 decimal128FromNumber(&x1, &d, &set);
3594 dfp128_set_cf_and_bxcf(&x1, DFP_CFS_SNAN);
3595 }
3596 else if (bexp == -1) /* Infinity */
3597 {
3598 /* Result is Infinity with re-encoded coefficient-continuation */
3599 dfp128_clear_cf_and_bxcf(&x3);
3600 decimal128ToNumber(&x3, &d);
3601 decimal128FromNumber(&x1, &d, &set);
3602 dfp128_set_cf_and_bxcf(&x1, DFP_CFS_INF);
3603 }
3604 else
3605 {
3606 decimal128ToNumber(&x3, &d);
3607 /* Clear CF and BXCF if source is Infinity or NaN */
3608 if (decNumberIsInfinite(&d) || decNumberIsNaN(&d))
3609 {
3610 dfp128_clear_cf_and_bxcf(&x3);
3611 decimal128ToNumber(&x3, &d);
3612 }
3613 /* Update exponent and re-encode coefficient-continuation */
3614 d.exponent = bexp - DECIMAL128_Bias;
3615 decimal128FromNumber(&x1, &d, &set);
3616 }
3617
3618 /* Load result into FP register r1 */
3619 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
3620
3621 } /* end DEF_INST(insert_biased_exponent_fix64_to_dfp_ext_reg) */
3622
3623
3624 /*-------------------------------------------------------------------*/
3625 /* B3F6 IEDTR - Insert Biased Exponent DFP Long Register [RRF] */
3626 /*-------------------------------------------------------------------*/
DEF_INST(insert_biased_exponent_fix64_to_dfp_long_reg)3627 DEF_INST(insert_biased_exponent_fix64_to_dfp_long_reg)
3628 {
3629 int r1, r2, r3; /* Values of R fields */
3630 decimal64 x1, x3; /* Long DFP values */
3631 decNumber d; /* Working decimal number */
3632 decContext set; /* Working context */
3633 S64 bexp; /* Biased exponent */
3634
3635 RRF_M(inst, regs, r1, r2, r3);
3636 DFPINST_CHECK(regs);
3637
3638 /* Initialise the context for long DFP */
3639 decContextDefault(&set, DEC_INIT_DECIMAL64);
3640
3641 /* Load biased exponent from general register r2 */
3642 bexp = (S64)(regs->GR(r2));
3643
3644 /* Load DFP long number from FP register r3 */
3645 ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs);
3646
3647 /* Insert biased exponent into number */
3648 if (bexp > DECIMAL64_Ehigh || bexp == -2 || bexp <= -4)
3649 {
3650 /* Result is a QNaN with re-encoded coefficient-continuation */
3651 dfp64_clear_cf_and_bxcf(&x3);
3652 decimal64ToNumber(&x3, &d);
3653 decimal64FromNumber(&x1, &d, &set);
3654 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_QNAN);
3655 }
3656 else if (bexp == -3)
3657 {
3658 /* Result is a SNaN with re-encoded coefficient-continuation */
3659 dfp64_clear_cf_and_bxcf(&x3);
3660 decimal64ToNumber(&x3, &d);
3661 decimal64FromNumber(&x1, &d, &set);
3662 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_SNAN);
3663 }
3664 else if (bexp == -1) /* Infinity */
3665 {
3666 /* Result is Infinity with re-encoded coefficient-continuation */
3667 dfp64_clear_cf_and_bxcf(&x3);
3668 decimal64ToNumber(&x3, &d);
3669 decimal64FromNumber(&x1, &d, &set);
3670 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_INF);
3671 }
3672 else
3673 {
3674 decimal64ToNumber(&x3, &d);
3675 /* Clear CF and BXCF if source is Infinity or NaN */
3676 if (decNumberIsInfinite(&d) || decNumberIsNaN(&d))
3677 {
3678 dfp64_clear_cf_and_bxcf(&x3);
3679 decimal64ToNumber(&x3, &d);
3680 }
3681 /* Update exponent and re-encode coefficient-continuation */
3682 d.exponent = bexp - DECIMAL64_Bias;
3683 decimal64FromNumber(&x1, &d, &set);
3684 }
3685
3686 /* Load result into FP register r1 */
3687 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
3688
3689 } /* end DEF_INST(insert_biased_exponent_fix64_to_dfp_long_reg) */
3690
3691
3692 /*-------------------------------------------------------------------*/
3693 /* B3DE LTXTR - Load and Test DFP Extended Register [RRE] */
3694 /*-------------------------------------------------------------------*/
DEF_INST(load_and_test_dfp_ext_reg)3695 DEF_INST(load_and_test_dfp_ext_reg)
3696 {
3697 int r1, r2; /* Values of R fields */
3698 decimal128 x1, x2; /* Extended DFP values */
3699 decNumber d; /* Working decimal number */
3700 decContext set; /* Working context */
3701 BYTE dxc; /* Data exception code */
3702
3703 RRE(inst, regs, r1, r2);
3704 DFPINST_CHECK(regs);
3705 DFPREGPAIR2_CHECK(r1, r2, regs);
3706
3707 /* Initialise the context for extended DFP */
3708 decContextDefault(&set, DEC_INIT_DECIMAL128);
3709
3710 /* Load value from FP register r2 */
3711 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
3712 decimal128ToNumber(&x2, &d);
3713
3714 /* For SNaN, force signaling condition and convert to QNaN */
3715 if (decNumberIsSNaN(&d))
3716 {
3717 set.status |= DEC_IEEE_854_Invalid_operation;
3718 d.bits &= ~DECSNAN;
3719 d.bits |= DECNAN;
3720 }
3721
3722 /* Check for exception condition */
3723 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
3724
3725 /* Reencode value and load into FP register r1 */
3726 decimal128FromNumber(&x1, &d, &set);
3727 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
3728
3729 /* Set condition code */
3730 regs->psw.cc = decNumberIsNaN(&d) ? 3 :
3731 decNumberIsZero(&d) ? 0 :
3732 decNumberIsNegative(&d) ? 1 : 2;
3733
3734 /* Raise data exception if error occurred */
3735 if (dxc != 0)
3736 {
3737 regs->dxc = dxc;
3738 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
3739 }
3740
3741 } /* end DEF_INST(load_and_test_dfp_ext_reg) */
3742
3743
3744 /*-------------------------------------------------------------------*/
3745 /* B3D6 LTDTR - Load and Test DFP Long Register [RRE] */
3746 /*-------------------------------------------------------------------*/
DEF_INST(load_and_test_dfp_long_reg)3747 DEF_INST(load_and_test_dfp_long_reg)
3748 {
3749 int r1, r2; /* Values of R fields */
3750 decimal64 x1, x2; /* Long DFP values */
3751 decNumber d; /* Working decimal number */
3752 decContext set; /* Working context */
3753 BYTE dxc; /* Data exception code */
3754
3755 RRE(inst, regs, r1, r2);
3756 DFPINST_CHECK(regs);
3757
3758 /* Initialise the context for long DFP */
3759 decContextDefault(&set, DEC_INIT_DECIMAL64);
3760
3761 /* Load value from FP register r2 */
3762 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
3763 decimal64ToNumber(&x2, &d);
3764
3765 /* For SNaN, force signaling condition and convert to QNaN */
3766 if (decNumberIsSNaN(&d))
3767 {
3768 set.status |= DEC_IEEE_854_Invalid_operation;
3769 d.bits &= ~DECSNAN;
3770 d.bits |= DECNAN;
3771 }
3772
3773 /* Check for exception condition */
3774 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
3775
3776 /* Reencode value and load into FP register r1 */
3777 decimal64FromNumber(&x1, &d, &set);
3778 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
3779
3780 /* Set condition code */
3781 regs->psw.cc = decNumberIsNaN(&d) ? 3 :
3782 decNumberIsZero(&d) ? 0 :
3783 decNumberIsNegative(&d) ? 1 : 2;
3784
3785 /* Raise data exception if error occurred */
3786 if (dxc != 0)
3787 {
3788 regs->dxc = dxc;
3789 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
3790 }
3791
3792 } /* end DEF_INST(load_and_test_dfp_long_reg) */
3793
3794
3795 /*-------------------------------------------------------------------*/
3796 /* B3DF FIXTR - Load FP Integer DFP Extended Register [RRF] */
3797 /*-------------------------------------------------------------------*/
DEF_INST(load_fp_int_dfp_ext_reg)3798 DEF_INST(load_fp_int_dfp_ext_reg)
3799 {
3800 int r1, r2, m3, m4; /* Values of R and M fields */
3801 decimal128 x1, x2; /* Extended DFP values */
3802 decNumber d1, d2, dc; /* Working decimal numbers */
3803 decContext set; /* Working context */
3804 BYTE dxc; /* Data exception code */
3805
3806 RRF_MM(inst, regs, r1, r2, m3, m4);
3807 DFPINST_CHECK(regs);
3808 DFPREGPAIR2_CHECK(r1, r2, regs);
3809
3810 /* Initialise the context for extended DFP */
3811 decContextDefault(&set, DEC_INIT_DECIMAL128);
3812 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
3813
3814 /* Load decimal number from FP register r2 */
3815 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
3816 decimal128ToNumber(&x2, &d2);
3817
3818 if (decNumberIsInfinite(&d2) == 0 && decNumberIsNaN(&d2) == 0)
3819 {
3820 /* Remove fractional part of decimal number */
3821 decNumberToIntegralValue(&d1, &d2, &set);
3822
3823 /* Raise inexact condition if M4 bit 1 is zero and
3824 result differs in value from original value */
3825 if ((m4 & 0x04) == 0)
3826 {
3827 decNumberCompare(&dc, &d1, &d2, &set);
3828 if (decNumberIsZero(&dc) == 0)
3829 {
3830 set.status |= DEC_IEEE_854_Inexact;
3831 if (decNumberIsNegative(&dc) == decNumberIsNegative(&d2))
3832 set.status |= DEC_Rounded;
3833 }
3834 }
3835 }
3836 else
3837 {
3838 /* Propagate NaN or default infinity */
3839 decNumberCopy(&d1, &d2);
3840
3841 /* For SNaN, force signaling condition and convert to QNaN */
3842 if (decNumberIsSNaN(&d2))
3843 {
3844 set.status |= DEC_IEEE_854_Invalid_operation;
3845 d1.bits &= ~DECSNAN;
3846 d1.bits |= DECNAN;
3847 }
3848 }
3849
3850 /* Convert result to extended DFP format */
3851 decimal128FromNumber(&x1, &d1, &set);
3852
3853 /* Check for exception condition */
3854 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
3855
3856 /* Load result into FP register r1 */
3857 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
3858
3859 /* Raise data exception if error occurred */
3860 if (dxc != 0)
3861 {
3862 regs->dxc = dxc;
3863 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
3864 }
3865
3866 } /* end DEF_INST(load_fp_int_dfp_ext_reg) */
3867
3868
3869 /*-------------------------------------------------------------------*/
3870 /* B3D7 FIDTR - Load FP Integer DFP Long Register [RRF] */
3871 /*-------------------------------------------------------------------*/
DEF_INST(load_fp_int_dfp_long_reg)3872 DEF_INST(load_fp_int_dfp_long_reg)
3873 {
3874 int r1, r2, m3, m4; /* Values of R and M fields */
3875 decimal64 x1, x2; /* Long DFP values */
3876 decNumber d1, d2, dc; /* Working decimal numbers */
3877 decContext set; /* Working context */
3878 BYTE dxc; /* Data exception code */
3879
3880 RRF_MM(inst, regs, r1, r2, m3, m4);
3881 DFPINST_CHECK(regs);
3882
3883 /* Initialise the context for long DFP */
3884 decContextDefault(&set, DEC_INIT_DECIMAL64);
3885 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
3886
3887 /* Load decimal number from FP register r2 */
3888 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
3889 decimal64ToNumber(&x2, &d2);
3890
3891 if (decNumberIsInfinite(&d2) == 0 && decNumberIsNaN(&d2) == 0)
3892 {
3893 /* Remove fractional part of decimal number */
3894 decNumberToIntegralValue(&d1, &d2, &set);
3895
3896 /* Raise inexact condition if M4 bit 1 is zero and
3897 result differs in value from original value */
3898 if ((m4 & 0x04) == 0)
3899 {
3900 decNumberCompare(&dc, &d1, &d2, &set);
3901 if (decNumberIsZero(&dc) == 0)
3902 {
3903 set.status |= DEC_IEEE_854_Inexact;
3904 if (decNumberIsNegative(&dc) == decNumberIsNegative(&d2))
3905 set.status |= DEC_Rounded;
3906 }
3907 }
3908 }
3909 else
3910 {
3911 /* Propagate NaN or default infinity */
3912 decNumberCopy(&d1, &d2);
3913
3914 /* For SNaN, force signaling condition and convert to QNaN */
3915 if (decNumberIsSNaN(&d2))
3916 {
3917 set.status |= DEC_IEEE_854_Invalid_operation;
3918 d1.bits &= ~DECSNAN;
3919 d1.bits |= DECNAN;
3920 }
3921 }
3922
3923 /* Convert result to long DFP format */
3924 decimal64FromNumber(&x1, &d1, &set);
3925
3926 /* Check for exception condition */
3927 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
3928
3929 /* Load result into FP register r1 */
3930 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
3931
3932 /* Raise data exception if error occurred */
3933 if (dxc != 0)
3934 {
3935 regs->dxc = dxc;
3936 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
3937 }
3938
3939 } /* end DEF_INST(load_fp_int_dfp_long_reg) */
3940
3941
3942 /*-------------------------------------------------------------------*/
3943 /* B3DC LXDTR - Load Lengthened DFP Long to Extended Register [RRF] */
3944 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_dfp_long_to_ext_reg)3945 DEF_INST(load_lengthened_dfp_long_to_ext_reg)
3946 {
3947 int r1, r2, m4; /* Values of R and M fields */
3948 decimal128 x1; /* Extended DFP value */
3949 decimal64 x2; /* Long DFP value */
3950 decNumber d1, d2; /* Working decimal numbers */
3951 decContext set; /* Working context */
3952 BYTE dxc; /* Data exception code */
3953
3954 RRF_M4(inst, regs, r1, r2, m4);
3955 DFPINST_CHECK(regs);
3956 DFPREGPAIR_CHECK(r1, regs);
3957
3958 /* Initialise the context for extended DFP */
3959 decContextDefault(&set, DEC_INIT_DECIMAL128);
3960
3961 /* Load DFP long number from FP register r2 */
3962 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
3963 decimal64ToNumber(&x2, &d2);
3964
3965 /* Convert number to DFP extended format */
3966 if (decNumberIsInfinite(&d2) && (m4 & 0x08))
3967 {
3968 /* For Inf with mask bit 0 set, propagate the digits */
3969 dfp64_clear_cf_and_bxcf(&x2);
3970 decimal64ToNumber(&x2, &d1);
3971 decimal128FromNumber(&x1, &d1, &set);
3972 dfp128_set_cf_and_bxcf(&x1, DFP_CFS_INF);
3973 }
3974 else if (decNumberIsNaN(&d2))
3975 {
3976 decimal64ToNumber(&x2, &d1);
3977 /* For SNaN with mask bit 0 off, convert to a QNaN
3978 and raise signaling condition */
3979 if (decNumberIsSNaN(&d2) && (m4 & 0x08) == 0)
3980 {
3981 set.status |= DEC_IEEE_854_Invalid_operation;
3982 d1.bits &= ~DECSNAN;
3983 d1.bits |= DECNAN;
3984 }
3985 decimal128FromNumber(&x1, &d1, &set);
3986 }
3987 else
3988 {
3989 decNumberCopy(&d1, &d2);
3990 decimal128FromNumber(&x1, &d1, &set);
3991 }
3992
3993 /* Check for exception condition */
3994 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
3995
3996 /* Load result into FP register r1 */
3997 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
3998
3999 /* Raise data exception if error occurred */
4000 if (dxc != 0)
4001 {
4002 regs->dxc = dxc;
4003 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
4004 }
4005
4006 } /* end DEF_INST(load_lengthened_dfp_long_to_ext_reg) */
4007
4008
4009 /*-------------------------------------------------------------------*/
4010 /* B3D4 LDETR - Load Lengthened DFP Short to Long Register [RRF] */
4011 /*-------------------------------------------------------------------*/
DEF_INST(load_lengthened_dfp_short_to_long_reg)4012 DEF_INST(load_lengthened_dfp_short_to_long_reg)
4013 {
4014 int r1, r2, m4; /* Values of R and M fields */
4015 decimal64 x1; /* Long DFP value */
4016 decimal32 x2; /* Short DFP value */
4017 decNumber d1, d2; /* Working decimal numbers */
4018 decContext set; /* Working context */
4019 BYTE dxc; /* Data exception code */
4020
4021 RRF_M4(inst, regs, r1, r2, m4);
4022 DFPINST_CHECK(regs);
4023
4024 /* Initialise the context for long DFP */
4025 decContextDefault(&set, DEC_INIT_DECIMAL64);
4026
4027 /* Load DFP short number from FP register r2 */
4028 ARCH_DEP(dfp_reg_to_decimal32)(r2, &x2, regs);
4029 decimal32ToNumber(&x2, &d2);
4030
4031 /* Convert number to DFP long format */
4032 if (decNumberIsInfinite(&d2) && (m4 & 0x08))
4033 {
4034 /* For Inf with mask bit 0 set, propagate the digits */
4035 dfp32_clear_cf_and_bxcf(&x2);
4036 decimal32ToNumber(&x2, &d1);
4037 decimal64FromNumber(&x1, &d1, &set);
4038 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_INF);
4039 }
4040 else if (decNumberIsNaN(&d2))
4041 {
4042 decimal32ToNumber(&x2, &d1);
4043 /* For SNaN with mask bit 0 off, convert to a QNaN
4044 and raise signaling condition */
4045 if (decNumberIsSNaN(&d2) && (m4 & 0x08) == 0)
4046 {
4047 set.status |= DEC_IEEE_854_Invalid_operation;
4048 d1.bits &= ~DECSNAN;
4049 d1.bits |= DECNAN;
4050 }
4051 decimal64FromNumber(&x1, &d1, &set);
4052 }
4053 else
4054 {
4055 decNumberCopy(&d1, &d2);
4056 decimal64FromNumber(&x1, &d1, &set);
4057 }
4058
4059 /* Check for exception condition */
4060 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
4061
4062 /* Load result into FP register r1 */
4063 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
4064
4065 /* Raise data exception if error occurred */
4066 if (dxc != 0)
4067 {
4068 regs->dxc = dxc;
4069 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
4070 }
4071
4072 } /* end DEF_INST(load_lengthened_dfp_short_to_long_reg) */
4073
4074
4075 /*-------------------------------------------------------------------*/
4076 /* B3DD LDXTR - Load Rounded DFP Extended to Long Register [RRF] */
4077 /*-------------------------------------------------------------------*/
DEF_INST(load_rounded_dfp_ext_to_long_reg)4078 DEF_INST(load_rounded_dfp_ext_to_long_reg)
4079 {
4080 int r1, r2, m3, m4; /* Values of R and M fields */
4081 decimal64 x1; /* Long DFP value */
4082 decimal128 x2; /* Extended DFP value */
4083 decNumber d1, d2; /* Working decimal numbers */
4084 decContext set; /* Working context */
4085 int32_t scale; /* Scaling factor */
4086 BYTE pwork[17]; /* 33-digit packed work area */
4087 BYTE dxc; /* Data exception code */
4088
4089 RRF_MM(inst, regs, r1, r2, m3, m4);
4090 DFPINST_CHECK(regs);
4091 DFPREGPAIR_CHECK(r2, regs);
4092
4093 /* Initialise the context for extended DFP */
4094 decContextDefault(&set, DEC_INIT_DECIMAL128);
4095 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
4096
4097 /* Load DFP extended number from FP register r2 */
4098 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
4099 decimal128ToNumber(&x2, &d2);
4100
4101 /* Convert number to DFP long format */
4102 if ((decNumberIsInfinite(&d2) && (m4 & 0x08))
4103 || decNumberIsNaN(&d2))
4104 {
4105 /* For Inf with mask bit 0 set, or for QNan or SNan,
4106 propagate the low 15 digits */
4107 dfp128_clear_cf_and_bxcf(&x2);
4108 decimal128ToNumber(&x2, &d1);
4109 decPackedFromNumber(pwork, sizeof(pwork), &scale, &d1);
4110 scale = 0;
4111 decPackedToNumber(pwork+sizeof(pwork)-8, 8, &scale, &d1);
4112 decimal64FromNumber(&x1, &d1, &set);
4113 if (decNumberIsInfinite(&d2))
4114 {
4115 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_INF);
4116 }
4117 else if (decNumberIsQNaN(&d2))
4118 {
4119 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_QNAN);
4120 }
4121 else /* it is an SNaN */
4122 {
4123 /* For SNaN with mask bit 0 off, convert to a QNaN
4124 and raise signaling condition */
4125 if (decNumberIsSNaN(&d2) && (m4 & 0x08) == 0)
4126 {
4127 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_QNAN);
4128 set.status |= DEC_IEEE_854_Invalid_operation;
4129 }
4130 else
4131 {
4132 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_SNAN);
4133 }
4134 }
4135 }
4136 else
4137 {
4138 /* For finite number, load value rounded to long DFP format,
4139 or for Inf with mask bit 0 not set, load default infinity */
4140 decNumberCopy(&d1, &d2);
4141 decimal64FromNumber(&x1, &d1, &set);
4142 }
4143
4144 /* Check for exception condition */
4145 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
4146
4147 /* Load result into FP register r1 */
4148 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
4149
4150 /* Raise data exception if error occurred */
4151 if (dxc != 0)
4152 {
4153 regs->dxc = dxc;
4154 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
4155 }
4156
4157 } /* end DEF_INST(load_rounded_dfp_ext_to_long_reg) */
4158
4159
4160 /*-------------------------------------------------------------------*/
4161 /* B3D5 LEDTR - Load Rounded DFP Long to Short Register [RRF] */
4162 /*-------------------------------------------------------------------*/
DEF_INST(load_rounded_dfp_long_to_short_reg)4163 DEF_INST(load_rounded_dfp_long_to_short_reg)
4164 {
4165 int r1, r2, m3, m4; /* Values of R and M fields */
4166 decimal32 x1; /* Short DFP value */
4167 decimal64 x2; /* Long DFP value */
4168 decNumber d1, d2; /* Working decimal numbers */
4169 decContext set; /* Working context */
4170 int32_t scale; /* Scaling factor */
4171 BYTE pwork[9]; /* 17-digit packed work area */
4172 BYTE dxc; /* Data exception code */
4173
4174 RRF_MM(inst, regs, r1, r2, m3, m4);
4175 DFPINST_CHECK(regs);
4176
4177 /* Initialise the context for long DFP */
4178 decContextDefault(&set, DEC_INIT_DECIMAL64);
4179 ARCH_DEP(dfp_rounding_mode)(&set, m3, regs);
4180
4181 /* Load DFP long number from FP register r2 */
4182 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
4183 decimal64ToNumber(&x2, &d2);
4184
4185 /* Convert number to DFP short format */
4186 if ((decNumberIsInfinite(&d2) && (m4 & 0x08))
4187 || decNumberIsNaN(&d2))
4188 {
4189 /* For Inf with mask bit 0 set, or for QNan or SNan,
4190 propagate the low 6 digits */
4191 dfp64_clear_cf_and_bxcf(&x2);
4192 decimal64ToNumber(&x2, &d1);
4193 decPackedFromNumber(pwork, sizeof(pwork), &scale, &d1);
4194 scale = 0;
4195 decPackedToNumber(pwork+sizeof(pwork)-4, 4, &scale, &d1);
4196 decimal32FromNumber(&x1, &d1, &set);
4197 if (decNumberIsInfinite(&d2))
4198 {
4199 dfp32_set_cf_and_bxcf(&x1, DFP_CFS_INF);
4200 }
4201 else if (decNumberIsQNaN(&d2))
4202 {
4203 dfp32_set_cf_and_bxcf(&x1, DFP_CFS_QNAN);
4204 }
4205 else /* it is an SNaN */
4206 {
4207 /* For SNaN with mask bit 0 off, convert to a QNaN
4208 and raise signaling condition */
4209 if (decNumberIsSNaN(&d2) && (m4 & 0x08) == 0)
4210 {
4211 dfp32_set_cf_and_bxcf(&x1, DFP_CFS_QNAN);
4212 set.status |= DEC_IEEE_854_Invalid_operation;
4213 }
4214 else
4215 {
4216 dfp32_set_cf_and_bxcf(&x1, DFP_CFS_SNAN);
4217 }
4218 }
4219 }
4220 else
4221 {
4222 /* For finite number, load value rounded to short DFP format,
4223 or for Inf with mask bit 0 not set, load default infinity */
4224 decNumberCopy(&d1, &d2);
4225 decimal32FromNumber(&x1, &d1, &set);
4226 }
4227
4228 /* Check for exception condition */
4229 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
4230
4231 /* Load result into FP register r1 */
4232 ARCH_DEP(dfp_reg_from_decimal32)(r1, &x1, regs);
4233
4234 /* Raise data exception if error occurred */
4235 if (dxc != 0)
4236 {
4237 regs->dxc = dxc;
4238 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
4239 }
4240
4241 } /* end DEF_INST(load_rounded_dfp_long_to_short_reg) */
4242
4243
4244 /*-------------------------------------------------------------------*/
4245 /* B3D8 MXTR - Multiply DFP Extended Register [RRR] */
4246 /*-------------------------------------------------------------------*/
DEF_INST(multiply_dfp_ext_reg)4247 DEF_INST(multiply_dfp_ext_reg)
4248 {
4249 int r1, r2, r3; /* Values of R fields */
4250 decimal128 x1, x2, x3; /* Extended DFP values */
4251 decNumber d1, d2, d3; /* Working decimal numbers */
4252 decContext set; /* Working context */
4253 BYTE dxc; /* Data exception code */
4254
4255 RRR(inst, regs, r1, r2, r3);
4256 DFPINST_CHECK(regs);
4257 DFPREGPAIR3_CHECK(r1, r2, r3, regs);
4258
4259 /* Initialise the context for extended DFP */
4260 decContextDefault(&set, DEC_INIT_DECIMAL128);
4261 ARCH_DEP(dfp_rounding_mode)(&set, 0, regs);
4262
4263 /* Multiply FP register r2 by FP register r3 */
4264 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
4265 ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs);
4266 decimal128ToNumber(&x2, &d2);
4267 decimal128ToNumber(&x3, &d3);
4268 decNumberMultiply(&d1, &d2, &d3, &set);
4269 decimal128FromNumber(&x1, &d1, &set);
4270
4271 /* Check for exception condition */
4272 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
4273
4274 /* Load result into FP register r1 */
4275 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
4276
4277 /* Raise data exception if error occurred */
4278 if (dxc != 0)
4279 {
4280 regs->dxc = dxc;
4281 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
4282 }
4283
4284 } /* end DEF_INST(multiply_dfp_ext_reg) */
4285
4286
4287 /*-------------------------------------------------------------------*/
4288 /* B3D0 MDTR - Multiply DFP Long Register [RRR] */
4289 /*-------------------------------------------------------------------*/
DEF_INST(multiply_dfp_long_reg)4290 DEF_INST(multiply_dfp_long_reg)
4291 {
4292 int r1, r2, r3; /* Values of R fields */
4293 decimal64 x1, x2, x3; /* Long DFP values */
4294 decNumber d1, d2, d3; /* Working decimal numbers */
4295 decContext set; /* Working context */
4296 BYTE dxc; /* Data exception code */
4297
4298 RRR(inst, regs, r1, r2, r3);
4299 DFPINST_CHECK(regs);
4300
4301 /* Initialise the context for long DFP */
4302 decContextDefault(&set, DEC_INIT_DECIMAL64);
4303 ARCH_DEP(dfp_rounding_mode)(&set, 0, regs);
4304
4305 /* Multiply FP register r2 by FP register r3 */
4306 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
4307 ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs);
4308 decimal64ToNumber(&x2, &d2);
4309 decimal64ToNumber(&x3, &d3);
4310 decNumberMultiply(&d1, &d2, &d3, &set);
4311 decimal64FromNumber(&x1, &d1, &set);
4312
4313 /* Check for exception condition */
4314 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
4315
4316 /* Load result into FP register r1 */
4317 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
4318
4319 /* Raise data exception if error occurred */
4320 if (dxc != 0)
4321 {
4322 regs->dxc = dxc;
4323 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
4324 }
4325
4326 } /* end DEF_INST(multiply_dfp_long_reg) */
4327
4328
4329 /*-------------------------------------------------------------------*/
4330 /* B3FD QAXTR - Quantize DFP Extended Register [RRF] */
4331 /*-------------------------------------------------------------------*/
DEF_INST(quantize_dfp_ext_reg)4332 DEF_INST(quantize_dfp_ext_reg)
4333 {
4334 int r1, r2, r3, m4; /* Values of R and M fields */
4335 decimal128 x1, x2, x3; /* Extended DFP values */
4336 decNumber d1, d2, d3; /* Working decimal numbers */
4337 decContext set; /* Working context */
4338 BYTE dxc; /* Data exception code */
4339
4340 RRF_RM(inst, regs, r1, r2, r3, m4);
4341 DFPINST_CHECK(regs);
4342 DFPREGPAIR3_CHECK(r1, r2, r3, regs);
4343
4344 /* Initialise the context for extended DFP */
4345 decContextDefault(&set, DEC_INIT_DECIMAL128);
4346 ARCH_DEP(dfp_rounding_mode)(&set, m4, regs);
4347
4348 /* Quantize FP register r3 using FP register r2 */
4349 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
4350 ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs);
4351 decimal128ToNumber(&x2, &d2);
4352 decimal128ToNumber(&x3, &d3);
4353 decNumberQuantize(&d1, &d2, &d3, &set);
4354 decimal128FromNumber(&x1, &d1, &set);
4355
4356 /* Check for exception condition */
4357 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
4358
4359 /* Load result into FP register r1 */
4360 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
4361
4362 /* Raise data exception if error occurred */
4363 if (dxc != 0)
4364 {
4365 regs->dxc = dxc;
4366 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
4367 }
4368
4369 } /* end DEF_INST(quantize_dfp_ext_reg) */
4370
4371
4372 /*-------------------------------------------------------------------*/
4373 /* B3F5 QADTR - Quantize DFP Long Register [RRF] */
4374 /*-------------------------------------------------------------------*/
DEF_INST(quantize_dfp_long_reg)4375 DEF_INST(quantize_dfp_long_reg)
4376 {
4377 int r1, r2, r3, m4; /* Values of R and M fields */
4378 decimal64 x1, x2, x3; /* Long DFP values */
4379 decNumber d1, d2, d3; /* Working decimal numbers */
4380 decContext set; /* Working context */
4381 BYTE dxc; /* Data exception code */
4382
4383 RRF_RM(inst, regs, r1, r2, r3, m4);
4384 DFPINST_CHECK(regs);
4385
4386 /* Initialise the context for long DFP */
4387 decContextDefault(&set, DEC_INIT_DECIMAL64);
4388 ARCH_DEP(dfp_rounding_mode)(&set, m4, regs);
4389
4390 /* Quantize FP register r3 using FP register r2 */
4391 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
4392 ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs);
4393 decimal64ToNumber(&x2, &d2);
4394 decimal64ToNumber(&x3, &d3);
4395 decNumberQuantize(&d1, &d2, &d3, &set);
4396 decimal64FromNumber(&x1, &d1, &set);
4397
4398 /* Check for exception condition */
4399 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
4400
4401 /* Load result into FP register r1 */
4402 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
4403
4404 /* Raise data exception if error occurred */
4405 if (dxc != 0)
4406 {
4407 regs->dxc = dxc;
4408 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
4409 }
4410
4411 } /* end DEF_INST(quantize_dfp_long_reg) */
4412
4413
4414 /*-------------------------------------------------------------------*/
4415 /* B3FF RRXTR - Reround DFP Extended Register [RRF] */
4416 /*-------------------------------------------------------------------*/
DEF_INST(reround_dfp_ext_reg)4417 DEF_INST(reround_dfp_ext_reg)
4418 {
4419 int signif; /* Requested significance */
4420 int r1, r2, r3, m4; /* Values of R and M fields */
4421 decimal128 x1, x3; /* Extended DFP values */
4422 decNumber d1, d3; /* Working decimal numbers */
4423 decContext set; /* Working context */
4424 BYTE dxc; /* Data exception code */
4425
4426 RRF_RM(inst, regs, r1, r2, r3, m4);
4427 DFPINST_CHECK(regs);
4428 DFPREGPAIR2_CHECK(r1, r3, regs);
4429
4430 /* Initialise the context for extended DFP */
4431 decContextDefault(&set, DEC_INIT_DECIMAL128);
4432 ARCH_DEP(dfp_rounding_mode)(&set, m4, regs);
4433
4434 /* Load significance from bits 58-63 of general register r2 */
4435 signif = regs->GR_L(r2) & 0x3F;
4436
4437 /* Reround FP register r3 */
4438 ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs);
4439 decimal128ToNumber(&x3, &d3);
4440 if (decNumberIsInfinite(&d3) || decNumberIsNaN(&d3)
4441 || decNumberIsZero(&d3)
4442 || signif == 0 || d3.digits <= signif)
4443 {
4444 decNumberCopy(&d1, &d3);
4445 }
4446 else
4447 {
4448 set.digits = signif;
4449 decNumberPlus(&d1, &d3, &set);
4450 }
4451 decimal128FromNumber(&x1, &d1, &set);
4452
4453 /* Check for exception condition */
4454 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
4455
4456 /* Load result into FP register r1 */
4457 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
4458
4459 /* Raise data exception if error occurred */
4460 if (dxc != 0)
4461 {
4462 regs->dxc = dxc;
4463 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
4464 }
4465
4466 } /* end DEF_INST(reround_dfp_ext_reg) */
4467
4468
4469 /*-------------------------------------------------------------------*/
4470 /* B3F7 RRDTR - Reround DFP Long Register [RRF] */
4471 /*-------------------------------------------------------------------*/
DEF_INST(reround_dfp_long_reg)4472 DEF_INST(reround_dfp_long_reg)
4473 {
4474 int signif; /* Requested significance */
4475 int r1, r2, r3, m4; /* Values of R and M fields */
4476 decimal64 x1, x3; /* Long DFP values */
4477 decNumber d1, d3; /* Working decimal numbers */
4478 decContext set; /* Working context */
4479 BYTE dxc; /* Data exception code */
4480
4481 RRF_RM(inst, regs, r1, r2, r3, m4);
4482 DFPINST_CHECK(regs);
4483
4484 /* Initialise the context for long DFP */
4485 decContextDefault(&set, DEC_INIT_DECIMAL64);
4486 ARCH_DEP(dfp_rounding_mode)(&set, m4, regs);
4487
4488 /* Load significance from bits 58-63 of general register r2 */
4489 signif = regs->GR_L(r2) & 0x3F;
4490
4491 /* Reround FP register r3 */
4492 ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs);
4493 decimal64ToNumber(&x3, &d3);
4494 if (decNumberIsInfinite(&d3) || decNumberIsNaN(&d3)
4495 || decNumberIsZero(&d3)
4496 || signif == 0 || d3.digits <= signif)
4497 {
4498 decNumberCopy(&d1, &d3);
4499 }
4500 else
4501 {
4502 set.digits = signif;
4503 decNumberPlus(&d1, &d3, &set);
4504 }
4505 decimal64FromNumber(&x1, &d1, &set);
4506
4507 /* Check for exception condition */
4508 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
4509
4510 /* Load result into FP register r1 */
4511 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
4512
4513 /* Raise data exception if error occurred */
4514 if (dxc != 0)
4515 {
4516 regs->dxc = dxc;
4517 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
4518 }
4519
4520 } /* end DEF_INST(reround_dfp_long_reg) */
4521
4522
4523 /*-------------------------------------------------------------------*/
4524 /* ED48 SLXT - Shift Coefficient Left DFP Extended [RXF] */
4525 /*-------------------------------------------------------------------*/
DEF_INST(shift_coefficient_left_dfp_ext)4526 DEF_INST(shift_coefficient_left_dfp_ext)
4527 {
4528 int r1, r3; /* Values of R fields */
4529 int b2; /* Base of effective addr */
4530 VADR effective_addr2; /* Effective address */
4531 decimal128 x1, x3; /* Extended DFP values */
4532 decNumber d1, d3; /* Working decimal numbers */
4533 decContext set; /* Working context */
4534 int n; /* Number of bits to shift */
4535
4536 RXF(inst, regs, r1, r3, b2, effective_addr2);
4537 DFPINST_CHECK(regs);
4538 DFPREGPAIR2_CHECK(r1, r3, regs);
4539
4540 /* Isolate rightmost 6 bits of second operand address */
4541 n = effective_addr2 & 0x3F;
4542
4543 /* Initialise the context for extended DFP */
4544 decContextDefault(&set, DEC_INIT_DECIMAL128);
4545
4546 /* Load DFP extended number from FP register r3 */
4547 ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs);
4548
4549 /* Convert to internal decimal number format */
4550 decimal128ToNumber(&x3, &d3);
4551
4552 /* For NaN and Inf use coefficient continuation digits only */
4553 if (decNumberIsNaN(&d3) || decNumberIsInfinite(&d3))
4554 {
4555 dfp128_clear_cf_and_bxcf(&x3);
4556 decimal128ToNumber(&x3, &d1);
4557 }
4558 else
4559 {
4560 decNumberCopy(&d1, &d3);
4561 }
4562
4563 /* Shift coefficient left n digit positions */
4564 dfp_shift_coeff(&set, &d1, n);
4565
4566 /* Convert result to DFP extended format */
4567 decimal128FromNumber(&x1, &d1, &set);
4568
4569 /* Restore Nan or Inf indicators in the result */
4570 if (decNumberIsQNaN(&d3))
4571 dfp128_set_cf_and_bxcf(&x1, DFP_CFS_QNAN);
4572 else if (decNumberIsSNaN(&d3))
4573 dfp128_set_cf_and_bxcf(&x1, DFP_CFS_SNAN);
4574 else if (decNumberIsInfinite(&d3))
4575 dfp128_set_cf_and_bxcf(&x1, DFP_CFS_INF);
4576
4577 /* Load result into FP register r1 */
4578 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
4579
4580 } /* end DEF_INST(shift_coefficient_left_dfp_ext) */
4581
4582
4583 /*-------------------------------------------------------------------*/
4584 /* ED40 SLDT - Shift Coefficient Left DFP Long [RXF] */
4585 /*-------------------------------------------------------------------*/
DEF_INST(shift_coefficient_left_dfp_long)4586 DEF_INST(shift_coefficient_left_dfp_long)
4587 {
4588 int r1, r3; /* Values of R fields */
4589 int b2; /* Base of effective addr */
4590 VADR effective_addr2; /* Effective address */
4591 decimal64 x1, x3; /* Long DFP values */
4592 decNumber d1, d3; /* Working decimal numbers */
4593 decContext set; /* Working context */
4594 int n; /* Number of bits to shift */
4595
4596 RXF(inst, regs, r1, r3, b2, effective_addr2);
4597 DFPINST_CHECK(regs);
4598
4599 /* Isolate rightmost 6 bits of second operand address */
4600 n = effective_addr2 & 0x3F;
4601
4602 /* Initialise the context for long DFP */
4603 decContextDefault(&set, DEC_INIT_DECIMAL64);
4604
4605 /* Load DFP long number from FP register r3 */
4606 ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs);
4607
4608 /* Convert to internal decimal number format */
4609 decimal64ToNumber(&x3, &d3);
4610
4611 /* For NaN and Inf use coefficient continuation digits only */
4612 if (decNumberIsNaN(&d3) || decNumberIsInfinite(&d3))
4613 {
4614 dfp64_clear_cf_and_bxcf(&x3);
4615 decimal64ToNumber(&x3, &d1);
4616 }
4617 else
4618 {
4619 decNumberCopy(&d1, &d3);
4620 }
4621
4622 /* Shift coefficient left n digit positions */
4623 dfp_shift_coeff(&set, &d1, n);
4624
4625 /* Convert result to DFP long format */
4626 decimal64FromNumber(&x1, &d1, &set);
4627
4628 /* Restore Nan or Inf indicators in the result */
4629 if (decNumberIsQNaN(&d3))
4630 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_QNAN);
4631 else if (decNumberIsSNaN(&d3))
4632 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_SNAN);
4633 else if (decNumberIsInfinite(&d3))
4634 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_INF);
4635
4636 /* Load result into FP register r1 */
4637 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
4638
4639 } /* end DEF_INST(shift_coefficient_left_dfp_long) */
4640
4641
4642 /*-------------------------------------------------------------------*/
4643 /* ED49 SRXT - Shift Coefficient Right DFP Extended [RXF] */
4644 /*-------------------------------------------------------------------*/
DEF_INST(shift_coefficient_right_dfp_ext)4645 DEF_INST(shift_coefficient_right_dfp_ext)
4646 {
4647 int r1, r3; /* Values of R fields */
4648 int b2; /* Base of effective addr */
4649 VADR effective_addr2; /* Effective address */
4650 decimal128 x1, x3; /* Extended DFP values */
4651 decNumber d1, d3; /* Working decimal numbers */
4652 decContext set; /* Working context */
4653 int n; /* Number of bits to shift */
4654
4655 RXF(inst, regs, r1, r3, b2, effective_addr2);
4656 DFPINST_CHECK(regs);
4657 DFPREGPAIR2_CHECK(r1, r3, regs);
4658
4659 /* Isolate rightmost 6 bits of second operand address */
4660 n = effective_addr2 & 0x3F;
4661
4662 /* Initialise the context for extended DFP */
4663 decContextDefault(&set, DEC_INIT_DECIMAL128);
4664
4665 /* Load DFP extended number from FP register r3 */
4666 ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs);
4667
4668 /* Convert to internal decimal number format */
4669 decimal128ToNumber(&x3, &d3);
4670
4671 /* For NaN and Inf use coefficient continuation digits only */
4672 if (decNumberIsNaN(&d3) || decNumberIsInfinite(&d3))
4673 {
4674 dfp128_clear_cf_and_bxcf(&x3);
4675 decimal128ToNumber(&x3, &d1);
4676 }
4677 else
4678 {
4679 decNumberCopy(&d1, &d3);
4680 }
4681
4682 /* Shift coefficient right n digit positions */
4683 dfp_shift_coeff(&set, &d1, -n);
4684
4685 /* Convert result to DFP extended format */
4686 decimal128FromNumber(&x1, &d1, &set);
4687
4688 /* Restore Nan or Inf indicators in the result */
4689 if (decNumberIsQNaN(&d3))
4690 dfp128_set_cf_and_bxcf(&x1, DFP_CFS_QNAN);
4691 else if (decNumberIsSNaN(&d3))
4692 dfp128_set_cf_and_bxcf(&x1, DFP_CFS_SNAN);
4693 else if (decNumberIsInfinite(&d3))
4694 dfp128_set_cf_and_bxcf(&x1, DFP_CFS_INF);
4695
4696 /* Load result into FP register r1 */
4697 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
4698
4699 } /* end DEF_INST(shift_coefficient_right_dfp_ext) */
4700
4701
4702 /*-------------------------------------------------------------------*/
4703 /* ED41 SRDT - Shift Coefficient Right DFP Long [RXF] */
4704 /*-------------------------------------------------------------------*/
DEF_INST(shift_coefficient_right_dfp_long)4705 DEF_INST(shift_coefficient_right_dfp_long)
4706 {
4707 int r1, r3; /* Values of R fields */
4708 int b2; /* Base of effective addr */
4709 VADR effective_addr2; /* Effective address */
4710 decimal64 x1, x3; /* Long DFP values */
4711 decNumber d1, d3; /* Working decimal numbers */
4712 decContext set; /* Working context */
4713 int n; /* Number of bits to shift */
4714
4715 RXF(inst, regs, r1, r3, b2, effective_addr2);
4716 DFPINST_CHECK(regs);
4717
4718 /* Isolate rightmost 6 bits of second operand address */
4719 n = effective_addr2 & 0x3F;
4720
4721 /* Initialise the context for long DFP */
4722 decContextDefault(&set, DEC_INIT_DECIMAL64);
4723
4724 /* Load DFP long number from FP register r3 */
4725 ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs);
4726
4727 /* Convert to internal decimal number format */
4728 decimal64ToNumber(&x3, &d3);
4729
4730 /* For NaN and Inf use coefficient continuation digits only */
4731 if (decNumberIsNaN(&d3) || decNumberIsInfinite(&d3))
4732 {
4733 dfp64_clear_cf_and_bxcf(&x3);
4734 decimal64ToNumber(&x3, &d1);
4735 }
4736 else
4737 {
4738 decNumberCopy(&d1, &d3);
4739 }
4740
4741 /* Shift coefficient right n digit positions */
4742 dfp_shift_coeff(&set, &d1, -n);
4743
4744 /* Convert result to DFP long format */
4745 decimal64FromNumber(&x1, &d1, &set);
4746
4747 /* Restore Nan or Inf indicators in the result */
4748 if (decNumberIsQNaN(&d3))
4749 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_QNAN);
4750 else if (decNumberIsSNaN(&d3))
4751 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_SNAN);
4752 else if (decNumberIsInfinite(&d3))
4753 dfp64_set_cf_and_bxcf(&x1, DFP_CFS_INF);
4754
4755 /* Load result into FP register r1 */
4756 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
4757
4758 } /* end DEF_INST(shift_coefficient_right_dfp_long) */
4759
4760
4761 /*-------------------------------------------------------------------*/
4762 /* B3DB SXTR - Subtract DFP Extended Register [RRR] */
4763 /*-------------------------------------------------------------------*/
DEF_INST(subtract_dfp_ext_reg)4764 DEF_INST(subtract_dfp_ext_reg)
4765 {
4766 int r1, r2, r3; /* Values of R fields */
4767 decimal128 x1, x2, x3; /* Extended DFP values */
4768 decNumber d1, d2, d3; /* Working decimal numbers */
4769 decContext set; /* Working context */
4770 BYTE dxc; /* Data exception code */
4771
4772 RRR(inst, regs, r1, r2, r3);
4773 DFPINST_CHECK(regs);
4774 DFPREGPAIR3_CHECK(r1, r2, r3, regs);
4775
4776 /* Initialise the context for extended DFP */
4777 decContextDefault(&set, DEC_INIT_DECIMAL128);
4778 ARCH_DEP(dfp_rounding_mode)(&set, 0, regs);
4779
4780 /* Subtract FP register r3 from FP register r2 */
4781 ARCH_DEP(dfp_reg_to_decimal128)(r2, &x2, regs);
4782 ARCH_DEP(dfp_reg_to_decimal128)(r3, &x3, regs);
4783 decimal128ToNumber(&x2, &d2);
4784 decimal128ToNumber(&x3, &d3);
4785 decNumberSubtract(&d1, &d2, &d3, &set);
4786 decimal128FromNumber(&x1, &d1, &set);
4787
4788 /* Check for exception condition */
4789 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
4790
4791 /* Load result into FP register r1 */
4792 ARCH_DEP(dfp_reg_from_decimal128)(r1, &x1, regs);
4793
4794 /* Set condition code */
4795 regs->psw.cc = decNumberIsNaN(&d1) ? 3 :
4796 decNumberIsZero(&d1) ? 0 :
4797 decNumberIsNegative(&d1) ? 1 : 2;
4798
4799 /* Raise data exception if error occurred */
4800 if (dxc != 0)
4801 {
4802 regs->dxc = dxc;
4803 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
4804 }
4805
4806 } /* end DEF_INST(subtract_dfp_ext_reg) */
4807
4808
4809 /*-------------------------------------------------------------------*/
4810 /* B3D3 SDTR - Subtract DFP Long Register [RRR] */
4811 /*-------------------------------------------------------------------*/
DEF_INST(subtract_dfp_long_reg)4812 DEF_INST(subtract_dfp_long_reg)
4813 {
4814 int r1, r2, r3; /* Values of R fields */
4815 decimal64 x1, x2, x3; /* Long DFP values */
4816 decNumber d1, d2, d3; /* Working decimal numbers */
4817 decContext set; /* Working context */
4818 BYTE dxc; /* Data exception code */
4819
4820 RRR(inst, regs, r1, r2, r3);
4821 DFPINST_CHECK(regs);
4822
4823 /* Initialise the context for long DFP */
4824 decContextDefault(&set, DEC_INIT_DECIMAL64);
4825 ARCH_DEP(dfp_rounding_mode)(&set, 0, regs);
4826
4827 /* Subtract FP register r3 from FP register r2 */
4828 ARCH_DEP(dfp_reg_to_decimal64)(r2, &x2, regs);
4829 ARCH_DEP(dfp_reg_to_decimal64)(r3, &x3, regs);
4830 decimal64ToNumber(&x2, &d2);
4831 decimal64ToNumber(&x3, &d3);
4832 decNumberSubtract(&d1, &d2, &d3, &set);
4833 decimal64FromNumber(&x1, &d1, &set);
4834
4835 /* Check for exception condition */
4836 dxc = ARCH_DEP(dfp_status_check)(&set, regs);
4837
4838 /* Load result into FP register r1 */
4839 ARCH_DEP(dfp_reg_from_decimal64)(r1, &x1, regs);
4840
4841 /* Set condition code */
4842 regs->psw.cc = decNumberIsNaN(&d1) ? 3 :
4843 decNumberIsZero(&d1) ? 0 :
4844 decNumberIsNegative(&d1) ? 1 : 2;
4845
4846 /* Raise data exception if error occurred */
4847 if (dxc != 0)
4848 {
4849 regs->dxc = dxc;
4850 ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
4851 }
4852
4853 } /* end DEF_INST(subtract_dfp_long_reg) */
4854
4855
4856 /*-------------------------------------------------------------------*/
4857 /* ED58 TDCXT - Test Data Class DFP Extended [RXE] */
4858 /*-------------------------------------------------------------------*/
DEF_INST(test_data_class_dfp_ext)4859 DEF_INST(test_data_class_dfp_ext)
4860 {
4861 int r1; /* Value of R field */
4862 int b2; /* Base of effective addr */
4863 VADR effective_addr2; /* Effective address */
4864 decimal128 x1; /* Extended DFP value */
4865 decNumber d1; /* Working decimal number */
4866 decContext set; /* Working context */
4867 U32 bits; /* Low 12 bits of address */
4868
4869 RXE(inst, regs, r1, b2, effective_addr2);
4870 DFPINST_CHECK(regs);
4871 DFPREGPAIR_CHECK(r1, regs);
4872
4873 /* Initialise the context for extended DFP */
4874 decContextDefault(&set, DEC_INIT_DECIMAL128);
4875
4876 /* Convert FP register r1 to decimal number format */
4877 ARCH_DEP(dfp_reg_to_decimal128)(r1, &x1, regs);
4878 decimal128ToNumber(&x1, &d1);
4879
4880 /* Isolate rightmost 12 bits of second operand address */
4881 bits = effective_addr2 & 0xFFF;
4882
4883 /* Test data class and set condition code */
4884 regs->psw.cc = dfp_test_data_class(&set, &d1, bits);
4885
4886 } /* end DEF_INST(test_data_class_dfp_ext) */
4887
4888
4889 /*-------------------------------------------------------------------*/
4890 /* ED54 TDCDT - Test Data Class DFP Long [RXE] */
4891 /*-------------------------------------------------------------------*/
DEF_INST(test_data_class_dfp_long)4892 DEF_INST(test_data_class_dfp_long)
4893 {
4894 int r1; /* Value of R field */
4895 int b2; /* Base of effective addr */
4896 VADR effective_addr2; /* Effective address */
4897 decimal64 x1; /* Long DFP value */
4898 decNumber d1; /* Working decimal number */
4899 decContext set; /* Working context */
4900 U32 bits; /* Low 12 bits of address */
4901
4902 RXE(inst, regs, r1, b2, effective_addr2);
4903 DFPINST_CHECK(regs);
4904
4905 /* Initialise the context for long DFP */
4906 decContextDefault(&set, DEC_INIT_DECIMAL64);
4907
4908 /* Convert FP register r1 to decimal number format */
4909 ARCH_DEP(dfp_reg_to_decimal64)(r1, &x1, regs);
4910 decimal64ToNumber(&x1, &d1);
4911
4912 /* Isolate rightmost 12 bits of second operand address */
4913 bits = effective_addr2 & 0xFFF;
4914
4915 /* Test data class and set condition code */
4916 regs->psw.cc = dfp_test_data_class(&set, &d1, bits);
4917
4918 } /* end DEF_INST(test_data_class_dfp_long) */
4919
4920
4921 /*-------------------------------------------------------------------*/
4922 /* ED50 TDCET - Test Data Class DFP Short [RXE] */
4923 /*-------------------------------------------------------------------*/
DEF_INST(test_data_class_dfp_short)4924 DEF_INST(test_data_class_dfp_short)
4925 {
4926 int r1; /* Value of R field */
4927 int b2; /* Base of effective addr */
4928 VADR effective_addr2; /* Effective address */
4929 decimal32 x1; /* Short DFP value */
4930 decNumber d1; /* Working decimal number */
4931 decContext set; /* Working context */
4932 U32 bits; /* Low 12 bits of address */
4933
4934 RXE(inst, regs, r1, b2, effective_addr2);
4935 DFPINST_CHECK(regs);
4936
4937 /* Initialise the context for short DFP */
4938 decContextDefault(&set, DEC_INIT_DECIMAL32);
4939
4940 /* Convert FP register r1 to decimal number format */
4941 ARCH_DEP(dfp_reg_to_decimal32)(r1, &x1, regs);
4942 decimal32ToNumber(&x1, &d1);
4943
4944 /* Isolate rightmost 12 bits of second operand address */
4945 bits = effective_addr2 & 0xFFF;
4946
4947 /* Test data class and set condition code */
4948 regs->psw.cc = dfp_test_data_class(&set, &d1, bits);
4949
4950 } /* end DEF_INST(test_data_class_dfp_short) */
4951
4952
4953 /*-------------------------------------------------------------------*/
4954 /* ED59 TDGXT - Test Data Group DFP Extended [RXE] */
4955 /*-------------------------------------------------------------------*/
DEF_INST(test_data_group_dfp_ext)4956 DEF_INST(test_data_group_dfp_ext)
4957 {
4958 int r1; /* Value of R field */
4959 int b2; /* Base of effective addr */
4960 VADR effective_addr2; /* Effective address */
4961 decimal128 x1; /* Extended DFP value */
4962 decNumber d1; /* Working decimal number */
4963 decContext set; /* Working context */
4964 U32 bits; /* Low 12 bits of address */
4965 int lmd; /* Leftmost digit */
4966
4967 RXE(inst, regs, r1, b2, effective_addr2);
4968 DFPINST_CHECK(regs);
4969 DFPREGPAIR_CHECK(r1, regs);
4970
4971 /* Initialise the context for extended DFP */
4972 decContextDefault(&set, DEC_INIT_DECIMAL128);
4973
4974 /* Load DFP extended number from FP register r1 */
4975 ARCH_DEP(dfp_reg_to_decimal128)(r1, &x1, regs);
4976
4977 /* Extract the leftmost digit from FP register r1 */
4978 lmd = dfp128_extract_lmd(&x1);
4979
4980 /* Convert to internal decimal number format */
4981 decimal128ToNumber(&x1, &d1);
4982
4983 /* Isolate rightmost 12 bits of second operand address */
4984 bits = effective_addr2 & 0xFFF;
4985
4986 /* Test data group and set condition code */
4987 regs->psw.cc = dfp_test_data_group(&set, &d1, lmd, bits);
4988
4989 } /* end DEF_INST(test_data_group_dfp_ext) */
4990
4991
4992 /*-------------------------------------------------------------------*/
4993 /* ED55 TDGDT - Test Data Group DFP Long [RXE] */
4994 /*-------------------------------------------------------------------*/
DEF_INST(test_data_group_dfp_long)4995 DEF_INST(test_data_group_dfp_long)
4996 {
4997 int r1; /* Value of R field */
4998 int b2; /* Base of effective addr */
4999 VADR effective_addr2; /* Effective address */
5000 decimal64 x1; /* Long DFP value */
5001 decNumber d1; /* Working decimal number */
5002 decContext set; /* Working context */
5003 U32 bits; /* Low 12 bits of address */
5004 int lmd; /* Leftmost digit */
5005
5006 RXE(inst, regs, r1, b2, effective_addr2);
5007 DFPINST_CHECK(regs);
5008
5009 /* Initialise the context for long DFP */
5010 decContextDefault(&set, DEC_INIT_DECIMAL64);
5011
5012 /* Load DFP long number from FP register r1 */
5013 ARCH_DEP(dfp_reg_to_decimal64)(r1, &x1, regs);
5014
5015 /* Extract the leftmost digit from FP register r1 */
5016 lmd = dfp64_extract_lmd(&x1);
5017
5018 /* Convert to internal decimal number format */
5019 decimal64ToNumber(&x1, &d1);
5020
5021 /* Isolate rightmost 12 bits of second operand address */
5022 bits = effective_addr2 & 0xFFF;
5023
5024 /* Test data group and set condition code */
5025 regs->psw.cc = dfp_test_data_group(&set, &d1, lmd, bits);
5026
5027 } /* end DEF_INST(test_data_group_dfp_long) */
5028
5029
5030 /*-------------------------------------------------------------------*/
5031 /* ED51 TDGET - Test Data Group DFP Short [RXE] */
5032 /*-------------------------------------------------------------------*/
DEF_INST(test_data_group_dfp_short)5033 DEF_INST(test_data_group_dfp_short)
5034 {
5035 int r1; /* Value of R field */
5036 int b2; /* Base of effective addr */
5037 VADR effective_addr2; /* Effective address */
5038 decimal32 x1; /* Short DFP value */
5039 decNumber d1; /* Working decimal number */
5040 decContext set; /* Working context */
5041 U32 bits; /* Low 12 bits of address */
5042 int lmd; /* Leftmost digit */
5043
5044 RXE(inst, regs, r1, b2, effective_addr2);
5045 DFPINST_CHECK(regs);
5046
5047 /* Initialise the context for short DFP */
5048 decContextDefault(&set, DEC_INIT_DECIMAL32);
5049
5050 /* Load DFP short number from FP register r1 */
5051 ARCH_DEP(dfp_reg_to_decimal32)(r1, &x1, regs);
5052
5053 /* Extract the leftmost digit from FP register r1 */
5054 lmd = dfp32_extract_lmd(&x1);
5055
5056 /* Convert to internal decimal number format */
5057 decimal32ToNumber(&x1, &d1);
5058
5059 /* Isolate rightmost 12 bits of second operand address */
5060 bits = effective_addr2 & 0xFFF;
5061
5062 /* Test data group and set condition code */
5063 regs->psw.cc = dfp_test_data_group(&set, &d1, lmd, bits);
5064
5065 } /* end DEF_INST(test_data_group_dfp_short) */
5066
5067 #endif /*defined(FEATURE_DECIMAL_FLOATING_POINT)*/
5068
5069 #if !defined(_GEN_ARCH)
5070
5071 #if defined(_ARCHMODE2)
5072 #define _GEN_ARCH _ARCHMODE2
5073 #include "dfp.c"
5074 #endif
5075
5076 #if defined(_ARCHMODE3)
5077 #undef _GEN_ARCH
5078 #define _GEN_ARCH _ARCHMODE3
5079 #include "dfp.c"
5080 #endif
5081
5082 #endif /*!defined(_GEN_ARCH)*/
5083
5084
5085 /* end of dfp.c */
5086