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