1 /* DECIMAL.C    (c) Copyright Roger Bowler, 1991-2009                */
2 /*              ESA/390 Packed Decimal Routines                      */
3 
4 /*-------------------------------------------------------------------*/
5 /* This module contains packed decimal subroutines for ESA/390.      */
6 /*                                                                   */
7 /* Acknowledgements:                                                 */
8 /*      The lowest level string-math functions are modelled on       */
9 /*      algorithms in D.E.Knuth's 'The Art of Computer Programming   */
10 /*      Vol.2', and on C.E.Burton's algorithms in DDJ #89.           */
11 /*-------------------------------------------------------------------*/
12 
13 /*-------------------------------------------------------------------*/
14 /* Complete rework for reworked instruction decode/execution code    */
15 /*                                               Jan Jaeger 01/07/00 */
16 /* Add trialrun to ED and EDMK                   Jan Jaeger 19/07/00 */
17 /* Fix random MP bug - Mario Bezzi                                   */
18 /* Clear DXC on data exception - Peter Kuschnerus                V209*/
19 /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009      */
20 /* TP instruction - Roger Bowler                            08/02/01 */
21 /* packed_to_binary subroutine - Roger Bowler               29/06/03 */
22 /* binary_to_packed subroutine - Roger Bowler              02jul2003 */
23 /*-------------------------------------------------------------------*/
24 
25 #include "hstdinc.h"
26 
27 #if !defined(_HENGINE_DLL_)
28 #define _HENGINE_DLL_
29 #endif
30 
31 #if !defined(_DECIMAL_C_)
32 #define _DECIMAL_C_
33 #endif
34 
35 #include "hercules.h"
36 
37 #include "opcode.h"
38 
39 #include "inline.h"
40 
41 #if !defined(_DECIMAL_C)
42 
43 #define _DECIMAL_C
44 
45 /*-------------------------------------------------------------------*/
46 /* Internal macro definitions                                        */
47 /*-------------------------------------------------------------------*/
48 #define MAX_DECIMAL_LENGTH      16
49 #define MAX_DECIMAL_DIGITS      (((MAX_DECIMAL_LENGTH)*2)-1)
50 
51 /*-------------------------------------------------------------------*/
52 /* Convert packed decimal number to binary                           */
53 /*                                                                   */
54 /* This subroutine is called by the CVB/CVBY/CVBG instructions.      */
55 /* It performs the conversion of a 8-byte or 16-byte packed          */
56 /* decimal number into a 64-bit SIGNED binary result.                */
57 /* This routine is not architecture-dependent; all of its operands   */
58 /* are contained in work areas passed by the architecture-dependent  */
59 /* instruction routines which handle all main-storage accesses and   */
60 /* possible program checks.                                          */
61 /*                                                                   */
62 /* Input:                                                            */
63 /*      dec     An 8 or 16 byte area containing a copy of the        */
64 /*              packed decimal storage operand.                      */
65 /*      len     Length-1 (in bytes) of the packed decimal input      */
66 /*              (7 for CVB/CVBY or 15 for CVBG).                     */
67 /* Output:                                                           */
68 /*      result  Points to an U64 field which will receive the        */
69 /*              result as a 64-bit SIGNED binary number.             */
70 /*      ovf     Points to an int field which will be set to 1 if     */
71 /*              the result overflows 63 bits plus sign, else 0.      */
72 /*              If overflow occurs, the result field will contain    */
73 /*              the rightmost 64 bits of the result.                 */
74 /*      dxf     Points to an int field which will be set to 1 if     */
75 /*              invalid digits or sign were detected, else 0.        */
76 /*              The result field is not set if the dxf is set to 1.  */
77 /*-------------------------------------------------------------------*/
packed_to_binary(BYTE * dec,int len,U64 * result,int * ovf,int * dxf)78 void packed_to_binary (BYTE *dec, int len, U64 *result,
79                         int *ovf, int *dxf)
80 {
81 U64     dreg;                           /* 64-bit result accumulator */
82 int     i;                              /* Loop counter              */
83 int     h, d=0;                         /* Decimal digits            */
84 U64     inter_u64max_div10;
85 int     inter_u64max_rem10;
86 U64     pos_u64max = 9223372036854775807ULL;  // (LLONG_MAX)
87 U64     neg_u64max = 9223372036854775808ULL;  // (LLONG_MIN)
88 
89     /* Initialize result flags */
90     *ovf = 0;
91     *dxf = 0;
92 
93     /* Initialize 64-bit result accumulator */
94     dreg = 0;
95 
96     /* Initialize max unsigned intermediate value for overflow check */
97     if ((dec[len] & 0x0F) == 0x0B ||
98         (dec[len] & 0x0F) == 0x0D)
99     {
100         inter_u64max_div10 =       (neg_u64max / 10);
101         inter_u64max_rem10 = (int) (neg_u64max % 10);
102     }
103     else if ((dec[len] & 0x0F) < 0x0A)
104     {
105         *dxf = 1;
106         return;
107     }
108     else
109     {
110         inter_u64max_div10 =       (pos_u64max / 10);
111         inter_u64max_rem10 = (int) (pos_u64max % 10);
112     }
113 
114     /* Convert decimal digits to binary */
115     for (i = 0; i <= len; i++)
116     {
117         /* Isolate high-order and low-order digits */
118         h = (dec[i] & 0xF0) >> 4;
119         d = dec[i] & 0x0F;
120 
121         /* Data exception if high-order digit is invalid */
122         if (h > 9)
123         {
124             *dxf = 1;
125             return;
126         }
127 
128         /* Check for overflow before accumulating */
129         if ( dreg >  inter_u64max_div10 ||
130             (dreg == inter_u64max_div10 &&
131                 h >  inter_u64max_rem10)) // (NOTE: 'h', not 'd')
132         {
133             *ovf = 1;
134         }
135 
136         /* Accumulate high-order digit into result */
137         dreg *= 10;
138         dreg += h;
139 
140         /* Check for valid low-order digit or sign */
141         if (i < len)
142         {
143             /* Data exception if low-order digit is invalid */
144             if (d > 9)
145             {
146                 *dxf = 1;
147                 return;
148             }
149 
150             /* Check for overflow before accumulating */
151             if ( dreg >  inter_u64max_div10 ||
152                 (dreg == inter_u64max_div10 &&
153                     d >  inter_u64max_rem10)) // (NOTE: 'd', not 'h')
154             {
155                 *ovf = 1;
156             }
157 
158             /* Accumulate low-order digit into result */
159             dreg *= 10;
160             dreg += d;
161         }
162         else
163         {
164             /* Data exception if sign is invalid */
165             if (d < 10)
166             {
167                 *dxf = 1;
168                 return;
169             }
170         }
171 
172     } /* end for(i) */
173 
174     /* Result is negative if sign is X'B' or X'D' */
175     if (d == 0x0B || d == 0x0D)
176     {
177         /* Check for UNDERflow (less than min negative) */
178         if ( dreg > neg_u64max )
179             *ovf = 1;
180         else
181         dreg = -((S64)dreg);
182     }
183     else
184     {
185         /* Check for OVERflow (greater than max positive) */
186         if ( dreg > pos_u64max )
187             *ovf = 1;
188     }
189 
190     /* Set result field and return */
191     *result = dreg;
192 
193 } /* end function packed_to_binary */
194 
195 /*-------------------------------------------------------------------*/
196 /* Convert binary number to packed decimal                           */
197 /*                                                                   */
198 /* This subroutine is called by the CVD/CVDY/CVDG instructions.      */
199 /* It performs the conversion of a 64-bit signed binary number       */
200 /* to a 16-byte packed decimal result. Since the maximum 63 bit      */
201 /* number is less than 31 decimal digits, overflow cannot occur.     */
202 /* Similarly, the maximum 31 bit number is less than 15 decimal      */
203 /* digits, therefore CVD/CVDY can safely use the rightmost eight     */
204 /* bytes of the packed decimal result without risk of overflow.      */
205 /*                                                                   */
206 /* This routine is not architecture-dependent; all of its operands   */
207 /* are contained in work areas passed by the architecture-dependent  */
208 /* instruction routines which handle all main-storage accesses and   */
209 /* possible program checks.                                          */
210 /*                                                                   */
211 /* Input:                                                            */
212 /*      bin     Binary number (63 bits plus sign)                    */
213 /* Output:                                                           */
214 /*      result  Points to a 16-byte field which will receive the     */
215 /*              result as a packed decimal number (31 digits + sign) */
216 /*-------------------------------------------------------------------*/
binary_to_packed(S64 bin,BYTE * result)217 void binary_to_packed (S64 bin, BYTE *result)
218 {
219 int     i;                              /* Array subscript           */
220 int     d;                              /* Decimal digit or sign     */
221 
222     /* Special case when input is maximum negative value */
223     if ((U64)bin == 0x8000000000000000ULL)
224     {
225         memcpy (result,
226                 "\x00\x00\x00\x00\x00\x00\x92\x23"
227                 "\x37\x20\x36\x85\x47\x75\x80\x8D",
228                 16);
229     }
230     else
231     {
232         /* Load absolute value and generate sign */
233         if ((U64)bin < 0x8000000000000000ULL)
234         {
235             /* Value is positive */
236             d = 0x0C;
237         }
238         else
239         {
240             /* Value is negative */
241             bin = -bin;
242             d = 0x0D;
243         }
244 
245         /* Store sign and decimal digits from right to left */
246         memset (result, 0, 16);
247         for (i = 16 - 1; d != 0 || bin != 0; i--)
248         {
249             result[i] = d;
250             d = bin % 10;
251             bin /= 10;
252             result[i] |= (d << 4);
253             d = bin % 10;
254             bin /= 10;
255         }
256     }
257 
258 } /* end function(binary_to_packed) */
259 
260 /*-------------------------------------------------------------------*/
261 /* Add two decimal byte strings as unsigned decimal numbers          */
262 /*                                                                   */
263 /* Input:                                                            */
264 /*      dec1    A 31-byte area containing the decimal digits of      */
265 /*              the first operand.  Each byte contains one decimal   */
266 /*              digit in the low-order 4 bits of the byte.           */
267 /*      dec2    A 31-byte area containing the decimal digits of      */
268 /*              the second operand.  Each byte contains one decimal  */
269 /*              digit in the low-order 4 bits of the byte.           */
270 /* Output:                                                           */
271 /*      result  Points to a 31-byte area to contain the result       */
272 /*              digits. One decimal digit is placed in the low-order */
273 /*              4 bits of each byte.                                 */
274 /*      count   Points to an integer to receive the number of        */
275 /*              digits in the result excluding leading zeroes.       */
276 /*              This field is set to zero if the result is all zero, */
277 /*              or to MAX_DECIMAL_DIGITS+1 if overflow occurred.     */
278 /*-------------------------------------------------------------------*/
add_decimal(BYTE * dec1,BYTE * dec2,BYTE * result,int * count)279 static void add_decimal (BYTE *dec1, BYTE *dec2,
280                         BYTE *result, int *count)
281 {
282 int     d;                              /* Decimal digit             */
283 int     i;                              /* Array subscript           */
284 int     n = 0;                          /* Significant digit counter */
285 int     carry = 0;                      /* Carry indicator           */
286 
287     /* Add digits from right to left */
288     for (i = MAX_DECIMAL_DIGITS - 1; i >= 0; i--)
289     {
290         /* Add digits from first and second operands */
291         d = dec1[i] + dec2[i] + carry;
292 
293         /* Check for carry into next digit */
294         if (d > 9) {
295             d -= 10;
296             carry = 1;
297         } else {
298             carry = 0;
299         }
300 
301         /* Check for significant digit */
302         if (d != 0)
303             n = MAX_DECIMAL_DIGITS - i;
304 
305         /* Store digit in result */
306         result[i] = d;
307 
308     } /* end for */
309 
310     /* Check for carry out of leftmost digit */
311     if (carry)
312         n = MAX_DECIMAL_DIGITS + 1;
313 
314     /* Return significant digit counter */
315     *count = n;
316 
317 } /* end function add_decimal */
318 
319 /*-------------------------------------------------------------------*/
320 /* Subtract two decimal byte strings as unsigned decimal numbers     */
321 /*                                                                   */
322 /* Input:                                                            */
323 /*      dec1    A 31-byte area containing the decimal digits of      */
324 /*              the first operand.  Each byte contains one decimal   */
325 /*              digit in the low-order 4 bits of the byte.           */
326 /*      dec2    A 31-byte area containing the decimal digits of      */
327 /*              the second operand.  Each byte contains one decimal  */
328 /*              digit in the low-order 4 bits of the byte.           */
329 /* Output:                                                           */
330 /*      result  Points to a 31-byte area to contain the result       */
331 /*              digits. One decimal digit is placed in the low-order */
332 /*              4 bits of each byte.                                 */
333 /*      count   Points to an integer to receive the number of        */
334 /*              digits in the result excluding leading zeroes.       */
335 /*              This field is set to zero if the result is all zero. */
336 /*      sign    -1 if the result is negative (operand2 > operand1)   */
337 /*              +1 if the result is positive (operand2 <= operand1)  */
338 /*-------------------------------------------------------------------*/
subtract_decimal(BYTE * dec1,BYTE * dec2,BYTE * result,int * count,int * sign)339 static void subtract_decimal (BYTE *dec1, BYTE *dec2,
340                         BYTE *result, int *count, int *sign)
341 {
342 int     d;                              /* Decimal digit             */
343 int     i;                              /* Array subscript           */
344 int     n = 0;                          /* Significant digit counter */
345 int     borrow = 0;                     /* Borrow indicator          */
346 int     rc;                             /* Return code               */
347 BYTE   *higher;                         /* -> Higher value operand   */
348 BYTE   *lower;                          /* -> Lower value operand    */
349 
350     /* Compare digits to find which operand has higher numeric value */
351     rc = memcmp (dec1, dec2, MAX_DECIMAL_DIGITS);
352 
353     /* Return positive zero result if both operands are equal */
354     if (rc == 0) {
355         memset (result, 0, MAX_DECIMAL_DIGITS);
356         *count = 0;
357         *sign = +1;
358         return;
359     }
360 
361     /* Point to higher and lower value operands and set sign */
362     if (rc > 0) {
363         higher = dec1;
364         lower = dec2;
365        *sign = +1;
366     } else {
367         lower = dec1;
368         higher = dec2;
369        *sign = -1;
370     }
371 
372     /* Subtract digits from right to left */
373     for (i = MAX_DECIMAL_DIGITS - 1; i >= 0; i--)
374     {
375         /* Subtract lower operand digit from higher operand digit */
376         d = higher[i] - lower[i] - borrow;
377 
378         /* Check for borrow from next digit */
379         if (d < 0) {
380             d += 10;
381             borrow = 1;
382         } else {
383             borrow = 0;
384         }
385 
386         /* Check for significant digit */
387         if (d != 0)
388             n = MAX_DECIMAL_DIGITS - i;
389 
390         /* Store digit in result */
391         result[i] = d;
392 
393     } /* end for */
394 
395     /* Return significant digit counter */
396     *count = n;
397 
398 } /* end function subtract_decimal */
399 
400 /*-------------------------------------------------------------------*/
401 /* Divide two decimal byte strings as unsigned decimal numbers       */
402 /*                                                                   */
403 /* Input:                                                            */
404 /*      dec1    A 31-byte area containing the decimal digits of      */
405 /*              the dividend.  Each byte contains one decimal        */
406 /*              digit in the low-order 4 bits of the byte.           */
407 /*      count1  The number of significant digits in the dividend.    */
408 /*      dec2    A 31-byte area containing the decimal digits of      */
409 /*              the divisor.  Each byte contains one decimal         */
410 /*              digit in the low-order 4 bits of the byte.           */
411 /*      count2  The number of significant digits in the divisor.     */
412 /* Output:                                                           */
413 /*      quot    Points to a 31-byte area to contain the quotient     */
414 /*              digits. One decimal digit is placed in the low-order */
415 /*              4 bits of each byte.                                 */
416 /*      rem     Points to a 31-byte area to contain the remainder    */
417 /*              digits. One decimal digit is placed in the low-order */
418 /*              4 bits of each byte.                                 */
419 /* Restrictions:                                                     */
420 /*      It is assumed that the caller has already verified that      */
421 /*      divide overflow cannot occur, that the divisor is not zero,  */
422 /*      and that the dividend has at least one high order zero.      */
423 /*-------------------------------------------------------------------*/
divide_decimal(BYTE * dec1,int count1,BYTE * dec2,int count2,BYTE * quot,BYTE * rem)424 static void divide_decimal (BYTE *dec1, int count1, BYTE *dec2,
425                         int count2, BYTE *quot, BYTE *rem)
426 {
427 BYTE   *num1;                           /* -> dividend digits        */
428 BYTE   *num2;                           /* -> divisor digits         */
429 int     div, flag, scale;               /* Work areas for algorithm  */
430 int     index, index1, index2;          /* Work areas for algorithm  */
431 int     indexq, indexr, temp1, temp2;   /* Work areas for algorithm  */
432 int     temp3, temp4, temp5, qtest;     /* Work areas for algorithm  */
433 
434     /* Clear the result fields */
435     memset (quot, 0, MAX_DECIMAL_DIGITS);
436     memset (rem, 0, MAX_DECIMAL_DIGITS);
437 
438     /* If dividend is zero then return zero quotient and remainder */
439     if (count1 == 0)
440         return;
441 
442     /* If dividend is less than divisor then return zero quotient
443        and set remainder equal to dividend */
444     if (memcmp (dec1, dec2, MAX_DECIMAL_DIGITS) < 0)
445     {
446         memcpy (rem, dec1, MAX_DECIMAL_DIGITS);
447         return;
448     }
449 
450     /* Adjust dividend digit count to give one leading zero */
451     count1++;
452 
453     /* Point to significant digits of dividend with leading zero */
454     num1 = dec1 + MAX_DECIMAL_DIGITS - count1;
455 
456     /* Point to significant digits of divisor */
457     num2 = dec2 + MAX_DECIMAL_DIGITS - count2;
458 
459     scale = 10 / (num2[0] + 1);
460     if (scale > 1)
461     {
462         for (index1 = count1-1, flag = 0; index1 >= 0; index1--)
463         {
464             div = flag + scale*num1[index1];
465             num1[index1] = div % 10;
466             flag = div / 10;
467         } /* end for(index1) */
468 
469         for (index2 = count2-1, flag = 0; index2 >= 0; index2--)
470         {
471             div = flag + scale*num2[index2];
472             num2[index2] = div % 10;
473             flag = div / 10;
474         } /* end for(index2) */
475 
476     } /* end if(scale>1) */
477 
478     for (index1 = 0; index1 < count1-count2; index1++)
479     {
480         if (num2[0] == num1[index1])
481             qtest = 9;
482         else
483         {
484             temp2 = (index1+1 < count1) ? num1[index1+1] : 0;
485             qtest = (10*num1[index1] + temp2) / num2[0];
486         }
487         temp2 = num1[index1];
488         temp4 = num2[0];
489         temp1 = (count2 >= 2) ? num2[1] : 0;
490         if (index1+1 < count1)
491         {
492             temp3 = num1[index1+1];
493             temp5 = (index1+2 < count1) ? num1[index1+2] : 0;
494         }
495         else
496         {
497             temp3 = 0;
498             temp5 = 0;
499         }
500         while (qtest*temp1 > (10*(10*temp2 + temp3
501                             - qtest*temp4) + temp5))
502             --qtest;
503 
504         for (index = index1+count2, index2 = count2-1, flag = 0;
505                 index >= index1; index--, index2--)
506         {
507             if (index2 >= 0)
508                 flag -= qtest*num2[index2];
509             div = flag + num1[index];
510             if (div < 0)
511             {
512                 flag = div / 10;
513                 div %= 10;
514                 if (div < 0)
515                 {
516                     div += 10;
517                     --flag;
518                 }
519             }
520             else
521                 flag = 0;
522             num1[index] = div;
523         } /* end for(index) */
524 
525         indexq = MAX_DECIMAL_DIGITS - (count1-count2) + index1;
526         if (flag != 0)
527         {
528             quot[indexq] = qtest - 1;
529             for (index = index1+count2, index2 = count2-1, flag = 0;
530                     index >= index1; index--, index2--)
531             {
532                 if (index2 >= 0)
533                     flag += num2[index2];
534                 div = flag + num1[index];
535                 if (div > 9)
536                 {
537                     div -= 10;
538                     flag = 1;
539                 }
540                 else
541                     flag = 0;
542                 num1[index] = div;
543             } /* end for(index) */
544         }
545         else
546             quot[indexq] = qtest;
547     } /* end for(index1) */
548 
549     for (index1 = count1-count2,
550             indexr = MAX_DECIMAL_DIGITS-count2, flag = 0;
551             index1 < count1; index1++, indexr++)
552     {
553         div = num1[index1] + 10*flag;
554         rem[indexr] = div / scale;
555         flag = div % scale;
556     } /* end for(index1) */
557 
558     for (index2 = 0, flag = 0; index2 < count2; index2++)
559     {
560         div = num2[index2] + 10*flag;
561         num2[index2] = div / scale;
562         flag = div % scale;
563     } /* end for(index2) */
564 
565 } /* end function divide_decimal */
566 
567 #endif /*!defined(_DECIMAL_C)*/
568 
569 /*-------------------------------------------------------------------*/
570 /* Load a packed decimal storage operand into a decimal byte string  */
571 /*                                                                   */
572 /* Input:                                                            */
573 /*      addr    Logical address of packed decimal storage operand    */
574 /*      len     Length minus one of storage operand (range 0-15)     */
575 /*      arn     Access register number associated with operand       */
576 /*      regs    CPU register context                                 */
577 /* Output:                                                           */
578 /*      result  Points to a 31-byte area into which the decimal      */
579 /*              digits are loaded.  One decimal digit is loaded      */
580 /*              into the low-order 4 bits of each byte, and the      */
581 /*              result is padded to the left with high-order zeroes  */
582 /*              if the storage operand contains less than 31 digits. */
583 /*      count   Points to an integer to receive the number of        */
584 /*              digits in the result excluding leading zeroes.       */
585 /*              This field is set to zero if the result is all zero. */
586 /*      sign    Points to an integer which will be set to -1 if a    */
587 /*              negative sign was loaded from the operand, or +1 if  */
588 /*              a positive sign was loaded from the operand.         */
589 /*                                                                   */
590 /*      A program check may be generated if the logical address      */
591 /*      causes an addressing, translation, or fetch protection       */
592 /*      exception, or if the operand causes a data exception         */
593 /*      because of invalid decimal digits or sign.                   */
594 /*-------------------------------------------------------------------*/
ARCH_DEP(load_decimal)595 static void ARCH_DEP(load_decimal) (VADR addr, int len, int arn, REGS *regs,
596                         BYTE *result, int *count, int *sign)
597 {
598 int     h;                              /* Hexadecimal digit         */
599 int     i, j;                           /* Array subscripts          */
600 int     n;                              /* Significant digit counter */
601 BYTE    pack[MAX_DECIMAL_LENGTH];       /* Packed decimal work area  */
602 
603     /* Fetch the packed decimal operand into work area */
604     memset (pack, 0, sizeof(pack));
605     ARCH_DEP(vfetchc) (pack+sizeof(pack)-len-1, len, addr, arn, regs);
606 
607     /* Unpack digits into result */
608     for (i=0, j=0, n=0; i < MAX_DECIMAL_DIGITS; i++)
609     {
610         /* Load source digit */
611         if (i & 1)
612             h = pack[j++] & 0x0F;
613         else
614             h = pack[j] >> 4;
615 
616         /* Check for valid numeric */
617         if (h > 9)
618         {
619             regs->dxc = DXC_DECIMAL;
620             ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
621             return;
622         }
623 
624         /* Count significant digits */
625         if (n > 0 || h != 0)
626             n++;
627 
628         /* Store decimal digit in result */
629         result[i] = h;
630 
631     } /* end for */
632 
633     /* Check for valid sign */
634     h = pack[MAX_DECIMAL_LENGTH-1] & 0x0F;
635     if (h < 0x0A)
636     {
637         regs->dxc = DXC_DECIMAL;
638         ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
639         return;
640     }
641 
642     /* Set number of significant digits */
643     *count = n;
644 
645     /* Set sign of operand */
646     *sign = (h == 0x0B || h == 0x0D) ? -1 : 1;
647 
648 } /* end function ARCH_DEP(load_decimal) */
649 
650 /*-------------------------------------------------------------------*/
651 /* Store decimal byte string into packed decimal storage operand     */
652 /*                                                                   */
653 /* Input:                                                            */
654 /*      addr    Logical address of packed decimal storage operand    */
655 /*      len     Length minus one of storage operand (range 0-15)     */
656 /*      arn     Access register number associated with operand       */
657 /*      regs    CPU register context                                 */
658 /*      dec     A 31-byte area containing the decimal digits to be   */
659 /*              stored.  Each byte contains one decimal digit in     */
660 /*              the low-order 4 bits of the byte.                    */
661 /*      sign    -1 if a negative sign is to be stored, or +1 if a    */
662 /*              positive sign is to be stored.                       */
663 /*                                                                   */
664 /*      A program check may be generated if the logical address      */
665 /*      causes an addressing, translation, or protection exception.  */
666 /*-------------------------------------------------------------------*/
ARCH_DEP(store_decimal)667 static void ARCH_DEP(store_decimal) (VADR addr, int len, int arn, REGS *regs,
668                         BYTE *dec, int sign)
669 {
670 int     i, j;                           /* Array subscripts          */
671 BYTE    pack[MAX_DECIMAL_LENGTH];       /* Packed decimal work area  */
672 
673     /* if operand crosses page, make sure both pages are accessable */
674     if((addr & PAGEFRAME_PAGEMASK) !=
675         ((addr + len) & PAGEFRAME_PAGEMASK))
676         ARCH_DEP(validate_operand) (addr, arn, len, ACCTYPE_WRITE_SKP, regs);
677 
678     /* Pack digits into packed decimal work area */
679     for (i=0, j=0; i < MAX_DECIMAL_DIGITS; i++)
680     {
681         if (i & 1)
682             pack[j++] |= dec[i];
683         else
684             pack[j] = dec[i] << 4;
685     } /* end for */
686 
687     /* Pack the sign into low-order digit of work area */
688     pack[MAX_DECIMAL_LENGTH-1] |= (sign < 0 ? 0x0D : 0x0C);
689 
690     /* Store the result at the operand location */
691     ARCH_DEP(vstorec) (pack+sizeof(pack)-len-1, len, addr, arn, regs);
692 
693 } /* end function ARCH_DEP(store_decimal) */
694 
695 
696 /*-------------------------------------------------------------------*/
697 /* FA   AP    - Add Decimal                                     [SS] */
698 /*-------------------------------------------------------------------*/
DEF_INST(add_decimal)699 DEF_INST(add_decimal)
700 {
701 int     l1, l2;                         /* Length values             */
702 int     b1, b2;                         /* Base register numbers     */
703 VADR    effective_addr1,
704         effective_addr2;                /* Effective addresses       */
705 int     cc;                             /* Condition code            */
706 BYTE    dec1[MAX_DECIMAL_DIGITS];       /* Work area for operand 1   */
707 BYTE    dec2[MAX_DECIMAL_DIGITS];       /* Work area for operand 2   */
708 BYTE    dec3[MAX_DECIMAL_DIGITS];       /* Work area for result      */
709 int     count1, count2, count3;         /* Significant digit counters*/
710 int     sign1, sign2, sign3;            /* Sign of operands & result */
711 
712     SS(inst, regs, l1, l2, b1, effective_addr1,
713                                      b2, effective_addr2);
714 
715     /* Load operands into work areas */
716     ARCH_DEP(load_decimal) (effective_addr1, l1, b1, regs, dec1, &count1, &sign1);
717     ARCH_DEP(load_decimal) (effective_addr2, l2, b2, regs, dec2, &count2, &sign2);
718 
719     /* Add or subtract operand values */
720     if (count2 == 0)
721     {
722         /* If second operand is zero then result is first operand */
723         memcpy (dec3, dec1, MAX_DECIMAL_DIGITS);
724         count3 = count1;
725         sign3 = sign1;
726     }
727     else if (count1 == 0)
728     {
729         /* If first operand is zero then result is second operand */
730         memcpy (dec3, dec2, MAX_DECIMAL_DIGITS);
731         count3 = count2;
732         sign3 = sign2;
733     }
734     else if (sign1 == sign2)
735     {
736         /* If signs are equal then add operands */
737         add_decimal (dec1, dec2, dec3, &count3);
738         sign3 = sign1;
739     }
740     else
741     {
742         /* If signs are opposite then subtract operands */
743         subtract_decimal (dec1, dec2, dec3, &count3, &sign3);
744         if (sign1 < 0) sign3 = -sign3;
745     }
746 
747     /* Set condition code */
748     cc = (count3 == 0) ? 0 : (sign3 < 1) ? 1 : 2;
749 
750     /* Overflow if result exceeds first operand length */
751     if (count3 > (l1+1) * 2 - 1)
752         cc = 3;
753 
754     /* Set positive sign if result is zero */
755     if (count3 == 0)
756         sign3 = 1;
757 
758     /* Store result into first operand location */
759     ARCH_DEP(store_decimal) (effective_addr1, l1, b1, regs, dec3, sign3);
760 
761     /* Set condition code */
762     regs->psw.cc = cc;
763 
764     /* Program check if overflow and PSW program mask is set */
765     if (cc == 3 && DOMASK(&regs->psw))
766         ARCH_DEP(program_interrupt) (regs, PGM_DECIMAL_OVERFLOW_EXCEPTION);
767 
768 } /* end DEF_INST(add_decimal) */
769 
770 
771 /*-------------------------------------------------------------------*/
772 /* F9   CP    - Compare Decimal                                 [SS] */
773 /*-------------------------------------------------------------------*/
DEF_INST(compare_decimal)774 DEF_INST(compare_decimal)
775 {
776 int     l1, l2;                         /* Length values             */
777 int     b1, b2;                         /* Base register numbers     */
778 VADR    effective_addr1,
779         effective_addr2;                /* Effective addresses       */
780 BYTE    dec1[MAX_DECIMAL_DIGITS];       /* Work area for operand 1   */
781 BYTE    dec2[MAX_DECIMAL_DIGITS];       /* Work area for operand 2   */
782 int     count1, count2;                 /* Significant digit counters*/
783 int     sign1, sign2;                   /* Sign of each operand      */
784 int     rc;                             /* Return code               */
785 
786     SS(inst, regs, l1, l2, b1, effective_addr1,
787                                      b2, effective_addr2);
788 
789     /* Load operands into work areas */
790     ARCH_DEP(load_decimal) (effective_addr1, l1, b1, regs, dec1, &count1, &sign1);
791     ARCH_DEP(load_decimal) (effective_addr2, l2, b2, regs, dec2, &count2, &sign2);
792 
793     /* Result is equal if both operands are zero */
794     if (count1 == 0 && count2 == 0)
795     {
796         regs->psw.cc = 0;
797         return;
798     }
799 
800     /* Result is low if operand 1 is -ve and operand 2 is +ve */
801     if (sign1 < 0 && sign2 > 0)
802     {
803         regs->psw.cc = 1;
804         return;
805     }
806 
807     /* Result is high if operand 1 is +ve and operand 2 is -ve */
808     if (sign1 > 0 && sign2 < 0)
809     {
810         regs->psw.cc = 2;
811         return;
812     }
813 
814     /* If signs are equal then compare the digits */
815     rc = memcmp (dec1, dec2, MAX_DECIMAL_DIGITS);
816 
817     /* Return low or high (depending on sign) if digits are unequal */
818     if (rc < 0)
819         regs->psw.cc = (sign1 > 0) ? 1 : 2;
820     else
821         if (rc > 0)
822             regs->psw.cc = (sign1 > 0) ? 2 : 1;
823         else
824             regs->psw.cc = 0;
825 
826 } /* end DEF_INST(compare_decimal) */
827 
828 
829 /*-------------------------------------------------------------------*/
830 /* FD   DP    - Divide Decimal                                  [SS] */
831 /*-------------------------------------------------------------------*/
DEF_INST(divide_decimal)832 DEF_INST(divide_decimal)
833 {
834 int     l1, l2;                         /* Length values             */
835 int     b1, b2;                         /* Base register numbers     */
836 VADR    effective_addr1,
837         effective_addr2;                /* Effective addresses       */
838 BYTE    dec1[MAX_DECIMAL_DIGITS];       /* Operand 1 (dividend)      */
839 BYTE    dec2[MAX_DECIMAL_DIGITS];       /* Operand 2 (divisor)       */
840 BYTE    quot[MAX_DECIMAL_DIGITS];       /* Quotient                  */
841 BYTE    rem[MAX_DECIMAL_DIGITS];        /* Remainder                 */
842 int     count1, count2;                 /* Significant digit counters*/
843 int     sign1, sign2;                   /* Sign of operands          */
844 int     signq, signr;                   /* Sign of quotient/remainder*/
845 
846     SS(inst, regs, l1, l2, b1, effective_addr1,
847                                      b2, effective_addr2);
848 
849     /* Program check if the second operand length exceeds 15 digits
850        or is equal to or greater than the first operand length */
851     if (l2 > 7 || l2 >= l1)
852         ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
853 
854     /* Load operands into work areas */
855     ARCH_DEP(load_decimal) (effective_addr1, l1, b1, regs, dec1, &count1, &sign1);
856     ARCH_DEP(load_decimal) (effective_addr2, l2, b2, regs, dec2, &count2, &sign2);
857 
858     /* Program check if second operand value is zero */
859     if (count2 == 0)
860         ARCH_DEP(program_interrupt) (regs, PGM_DECIMAL_DIVIDE_EXCEPTION);
861 
862     /* Perform trial comparison to determine potential overflow.
863        The leftmost digit of the divisor is aligned one digit to
864        the right of the leftmost dividend digit.  When the divisor,
865        so aligned, is less than or equal to the dividend, ignoring
866        signs, a divide exception is indicated.  As a result of this
867        comparison, it is also certain that the leftmost digit of the
868        dividend must be zero, and that the divisor cannot be zero */
869     if (memcmp(dec2 + (MAX_DECIMAL_DIGITS - l2*2 - 2),
870                 dec1 + (MAX_DECIMAL_DIGITS - l1*2 - 1),
871                 l2*2 + 2) <= 0)
872         ARCH_DEP(program_interrupt) (regs, PGM_DECIMAL_DIVIDE_EXCEPTION);
873 
874     /* Perform decimal division */
875     divide_decimal (dec1, count1, dec2, count2, quot, rem);
876 
877     /* Quotient is positive if operand signs are equal, and negative
878        if operand signs are opposite, even if quotient is zero */
879     signq = (sign1 == sign2) ? 1 : -1;
880 
881     /* Remainder sign is same as dividend, even if remainder is zero */
882     signr = sign1;
883 
884     /* Store remainder into entire first operand location.  The entire
885        field will be filled in order to check for store protection.
886        Subsequently the quotient will be stored in the leftmost bytes
887        of the first operand location, overwriting high order zeroes */
888     ARCH_DEP(store_decimal) (effective_addr1, l1, b1, regs, rem, signr);
889 
890     /* Store quotient in leftmost bytes of first operand location */
891     ARCH_DEP(store_decimal) (effective_addr1, l1-l2-1, b1, regs, quot, signq);
892 
893 } /* end DEF_INST(divide_decimal) */
894 
895 
896 /*-------------------------------------------------------------------*/
897 /* DE   ED    - Edit                                            [SS] */
898 /* DF   EDMK  - Edit and Mark                                   [SS] */
899 /*-------------------------------------------------------------------*/
DEF_INST(edit_x_edit_and_mark)900 DEF_INST(edit_x_edit_and_mark)
901 {
902 int     l;                              /* Length value              */
903 int     b1, b2;                         /* Base register numbers     */
904 VADR    effective_addr1,
905         effective_addr2,                /* Effective addresses       */
906         addr1,
907         addr2;
908 int     cc = 0;                         /* Condition code            */
909 int     sig = 0;                        /* Significance indicator    */
910 int     trial_run;                      /* 1=trial run               */
911 int     i;                              /* Loop counter              */
912 int     d;                              /* 1=Use right source digit  */
913 int     h;                              /* Hexadecimal digit         */
914 BYTE    sbyte;                          /* Source operand byte       */
915 BYTE    fbyte;                          /* Fill byte                 */
916 BYTE    pbyte;                          /* Pattern byte              */
917 BYTE    rbyte;                          /* Result byte               */
918 
919     SS_L(inst, regs, l, b1, effective_addr1,
920                                   b2, effective_addr2);
921 
922     /* If addr1 crosses page, make sure both pages are accessable */
923     if((effective_addr1 & PAGEFRAME_PAGEMASK) !=
924         ((effective_addr1 + l) & PAGEFRAME_PAGEMASK))
925         ARCH_DEP(validate_operand) (effective_addr1, b1, l, ACCTYPE_WRITE_SKP, regs);
926 
927     /* If addr2 might cross page, do a trial run to catch possible access rupts */
928     if((effective_addr2 & PAGEFRAME_PAGEMASK) !=
929         ((effective_addr2 + l) & PAGEFRAME_PAGEMASK))
930         trial_run = 1;
931     else
932         trial_run = 0;
933 
934     for(;trial_run >= 0; trial_run--)
935     {
936         /* Initialize variables */
937         addr1 = effective_addr1;
938         addr2 = effective_addr2;
939         cc = 0;
940         sig = 0;
941         sbyte = 0;
942         fbyte = 0;
943 
944         /* Process first operand from left to right */
945         for (i = 0, d = 0; i < l+1; i++)
946         {
947             /* Fetch pattern byte from first operand */
948             pbyte = ARCH_DEP(vfetchb) ( addr1, b1, regs );
949 
950             /* The first pattern byte is also the fill byte */
951             if (i == 0) fbyte = pbyte;
952 
953             /* If pattern byte is digit selector (X'20') or
954                significance starter (X'21') then fetch next
955                hexadecimal digit from the second operand */
956             if (pbyte == 0x20 || pbyte == 0x21)
957             {
958                 if (d == 0)
959                 {
960                     /* Fetch source byte and extract left digit */
961                     sbyte = ARCH_DEP(vfetchb) ( addr2, b2, regs );
962                     h = sbyte >> 4;
963                     sbyte &= 0x0F;
964                     d = 1;
965 
966                     /* Increment second operand address */
967                     addr2++;
968                     addr2 &= ADDRESS_MAXWRAP(regs);
969 
970                     /* Program check if left digit is not numeric */
971                     if (h > 9)
972                     {
973                         regs->dxc = DXC_DECIMAL;
974                         ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
975                     }
976 
977                 }
978                 else
979                 {
980                     /* Use right digit of source byte */
981                     h = sbyte;
982                     d = 0;
983                 }
984 
985                 /* For the EDMK instruction only, insert address of
986                    result byte into general register 1 if the digit
987                    is non-zero and significance indicator was off */
988                 if (!trial_run && (inst[0] == 0xDF) && h > 0 && sig == 0)
989                 {
990 #if defined(FEATURE_ESAME)
991                     if (regs->psw.amode64)
992                         regs->GR_G(1) = addr1;
993                     else
994 #endif
995                     if ( regs->psw.amode )
996                         regs->GR_L(1) = addr1;
997                     else
998                         regs->GR_LA24(1) = addr1;
999                 }
1000 
1001                 /* Replace the pattern byte by the fill character
1002                    or by a zoned decimal digit */
1003                 rbyte = (sig == 0 && h == 0) ? fbyte : (0xF0 | h);
1004                 if(!trial_run)
1005                     ARCH_DEP(vstoreb) ( rbyte, addr1, b1, regs );
1006                 else
1007                     ARCH_DEP(validate_operand) (addr1, b1, 0, ACCTYPE_WRITE_SKP, regs);
1008 
1009                 /* Set condition code 2 if digit is non-zero */
1010                 if (h > 0) cc = 2;
1011 
1012                 /* Turn on significance indicator if pattern
1013                    byte is significance starter or if source
1014                    digit is non-zero */
1015                 if (pbyte == 0x21 || h > 0)
1016                     sig = 1;
1017 
1018                 /* Examine right digit for sign code */
1019                 if (d == 1 && sbyte > 9)
1020                 {
1021                     /* Turn off the significance indicator if
1022                        the right digit is a plus sign code */
1023                     if (sbyte != 0x0B && sbyte != 0x0D)
1024                         sig = 0;
1025 
1026                     /* Take next digit from next source byte */
1027                     d = 0;
1028                 }
1029             }
1030 
1031             /* If pattern byte is field separator (X'22') then
1032                replace it by the fill character, turn off the
1033                significance indicator, and zeroize conditon code  */
1034             else if (pbyte == 0x22)
1035             {
1036                 if(!trial_run)
1037                     ARCH_DEP(vstoreb) ( fbyte, addr1, b1, regs );
1038                 else
1039                     ARCH_DEP(validate_operand) (addr1, b1, 0, ACCTYPE_WRITE_SKP, regs);
1040                 sig = 0;
1041                 cc = 0;
1042             }
1043 
1044             /* If pattern byte is a message byte (anything other
1045                than X'20', X'21', or X'22') then replace it by
1046                the fill byte if the significance indicator is off */
1047             else
1048             {
1049                 if (sig == 0)
1050                 {
1051                     if (!trial_run)
1052                         ARCH_DEP(vstoreb) ( fbyte, addr1, b1, regs );
1053                     else
1054                         ARCH_DEP(validate_operand) (addr1, b1, 0, ACCTYPE_WRITE_SKP, regs);
1055                 }
1056                 else /* store message byte */
1057                 {
1058                     if (!trial_run)
1059                         ARCH_DEP(vstoreb) ( pbyte, addr1, b1, regs );
1060                     else
1061                         ARCH_DEP(validate_operand) (addr1, b1, 0, ACCTYPE_WRITE_SKP, regs);
1062                 }
1063             }
1064 
1065             /* Increment first operand address */
1066             addr1++;
1067             addr1 &= ADDRESS_MAXWRAP(regs);
1068 
1069         } /* end for(i) */
1070 
1071     } /* end for(trial_run) */
1072 
1073     /* Replace condition code 2 by condition code 1 if the
1074        significance indicator is on at the end of editing */
1075     if (sig && cc == 2) cc = 1;
1076 
1077     /* Set condition code */
1078     regs->psw.cc = cc;
1079 
1080 } /* end DEF_INST(edit_x_edit_and_mark) */
1081 
1082 
1083 /*-------------------------------------------------------------------*/
1084 /* FC   MP    - Multiply Decimal                                [SS] */
1085 /*-------------------------------------------------------------------*/
DEF_INST(multiply_decimal)1086 DEF_INST(multiply_decimal)
1087 {
1088 int     l1, l2;                         /* Length values             */
1089 int     b1, b2;                         /* Base register numbers     */
1090 VADR    effective_addr1,
1091         effective_addr2;                /* Effective addresses       */
1092 BYTE    dec1[MAX_DECIMAL_DIGITS];       /* Work area for operand 1   */
1093 BYTE    dec2[MAX_DECIMAL_DIGITS];       /* Work area for operand 2   */
1094 BYTE    dec3[MAX_DECIMAL_DIGITS];       /* Work area for result      */
1095 int     count1, count2;                 /* Significant digit counters*/
1096 int     sign1, sign2, sign3;            /* Sign of operands & result */
1097 int     d;                              /* Decimal digit             */
1098 int     i1, i2, i3;                     /* Array subscripts          */
1099 int     carry;                          /* Carry indicator           */
1100 
1101     SS(inst, regs, l1, l2, b1, effective_addr1,
1102                                      b2, effective_addr2);
1103 
1104     /* Program check if the second operand length exceeds 15 digits
1105        or is equal to or greater than the first operand length */
1106     if (l2 > 7 || l2 >= l1)
1107         ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
1108 
1109     /* Load operands into work areas */
1110     ARCH_DEP(load_decimal) (effective_addr1, l1, b1, regs, dec1, &count1, &sign1);
1111     ARCH_DEP(load_decimal) (effective_addr2, l2, b2, regs, dec2, &count2, &sign2);
1112 
1113     /* Program check if the number of bytes in the second operand
1114        is less than the number of bytes of high-order zeroes in the
1115        first operand; this ensures that overflow cannot occur */
1116     if (l2 > l1 - (count1/2 + 1))
1117     {
1118         regs->dxc = DXC_DECIMAL;
1119         ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
1120     }
1121 
1122     /* Clear the result field */
1123     memset (dec3, 0, MAX_DECIMAL_DIGITS);
1124 
1125     /* Perform decimal multiplication */
1126     for (i2 = MAX_DECIMAL_DIGITS-1; i2 >= 0; i2--)
1127     {
1128         if (dec2[i2] != 0)
1129         {
1130             for (i1 = MAX_DECIMAL_DIGITS - 1, i3 = i2, carry = 0;
1131                         i3 >= 0; i1--, i3--)
1132             {
1133                 d = carry + dec1[i1]*dec2[i2] + dec3[i3];
1134                 dec3[i3] = d % 10;
1135                 carry = d / 10;
1136             }
1137         }
1138     } /* end for(i2) */
1139 
1140     /* Result is positive if operand signs are equal, and negative
1141        if operand signs are opposite, even if result is zero */
1142     sign3 = (sign1 == sign2) ? 1 : -1;
1143 
1144     /* Store result into first operand location */
1145     ARCH_DEP(store_decimal) (effective_addr1, l1, b1, regs, dec3, sign3);
1146 
1147 } /* end DEF_INST(multiply_decimal) */
1148 
1149 
1150 #if defined(_MSVC_) && (_MSC_VER == 1900)
1151 #pragma optimize( "g", off )
1152 #endif
1153 
1154 /*-------------------------------------------------------------------*/
1155 /* F0   SRP   - Shift and Round Decimal                         [SS] */
1156 /*-------------------------------------------------------------------*/
DEF_INST(shift_and_round_decimal)1157 DEF_INST(shift_and_round_decimal)
1158 {
1159 int     l1, i3;                         /* Length and rounding       */
1160 int     b1, b2;                         /* Base register numbers     */
1161 VADR    effective_addr1,
1162         effective_addr2;                /* Effective addresses       */
1163 int     cc;                             /* Condition code            */
1164 BYTE    dec[MAX_DECIMAL_DIGITS];        /* Work area for operand     */
1165 int     count;                          /* Significant digit counter */
1166 int     sign;                           /* Sign of operand/result    */
1167 int     i, j;                           /* Array subscripts          */
1168 int     d;                              /* Decimal digit             */
1169 int     carry;                          /* Carry indicator           */
1170 
1171     SS(inst, regs, l1, i3, b1, effective_addr1,
1172                                      b2, effective_addr2);
1173 
1174     /* Load operand into work area */
1175     ARCH_DEP(load_decimal) (effective_addr1, l1, b1, regs, dec, &count, &sign);
1176 
1177     /* Program check if rounding digit is invalid */
1178     if (i3 > 9)
1179     {
1180         regs->dxc = DXC_DECIMAL;
1181         ARCH_DEP(program_interrupt) (regs, PGM_DATA_EXCEPTION);
1182     }
1183 
1184     /* Isolate low-order six bits of shift count */
1185     effective_addr2 &= 0x3F;
1186 
1187     /* Shift count 0-31 means shift left, 32-63 means shift right */
1188     if (effective_addr2 < 32)
1189     {
1190         /* Set condition code according to operand sign */
1191         cc = (count == 0) ? 0 : (sign < 0) ? 1 : 2;
1192 
1193         /* Set cc=3 if non-zero digits will be lost on left shift */
1194         if (count > 0 && effective_addr2 > (VADR)((l1+1)*2 - 1 - count))
1195             cc = 3;
1196 
1197         /* Shift operand left */
1198         for (i=0, j=effective_addr2; i < MAX_DECIMAL_DIGITS; i++, j++)
1199             dec[i] = (j < MAX_DECIMAL_DIGITS) ? dec[j] : 0;
1200     }
1201     else
1202     {
1203         /* Calculate number of digits (1-32) to shift right */
1204         effective_addr2 = 64 - effective_addr2;
1205 
1206         /* Add the rounding digit to the leftmost of the digits
1207            to be shifted out and propagate the carry to the left */
1208         carry = (effective_addr2 > MAX_DECIMAL_DIGITS) ? 0 :
1209                 (dec[MAX_DECIMAL_DIGITS - effective_addr2] + i3) / 10;
1210         count = 0;
1211 
1212         /* Shift operand right */
1213         for (i=MAX_DECIMAL_DIGITS-1, j=MAX_DECIMAL_DIGITS-1-effective_addr2;
1214                 i >= 0; i--, j--)
1215         {
1216             d = (j >= 0) ? dec[j] : 0;
1217             d += carry;
1218             carry = d / 10;
1219             d %= 10;
1220             dec[i] = d;
1221             if (d != 0)
1222                 count = MAX_DECIMAL_DIGITS - i;
1223         }
1224 
1225         /* Set condition code according to operand sign */
1226         cc = (count == 0) ? 0 : (sign < 0) ? 1 : 2;
1227     }
1228 
1229     /* Make sign positive if result is zero */
1230     if (cc == 0)
1231         sign = +1;
1232 
1233     /* Store result into operand location */
1234     ARCH_DEP(store_decimal) (effective_addr1, l1, b1, regs, dec, sign);
1235 
1236     /* Set condition code */
1237     regs->psw.cc = cc;
1238 
1239     /* Program check if overflow and PSW program mask is set */
1240     if (cc == 3 && DOMASK(&regs->psw))
1241         ARCH_DEP(program_interrupt) (regs, PGM_DECIMAL_OVERFLOW_EXCEPTION);
1242 
1243 } /* end DEF_INST(shift_and_round_decimal) */
1244 
1245 #if defined(_MSVC_) && (_MSC_VER >= 1600)
1246 #pragma optimize( "", on )
1247 #endif
1248 
1249 
1250 /*-------------------------------------------------------------------*/
1251 /* FB   SP    - Subtract Decimal                                [SS] */
1252 /*-------------------------------------------------------------------*/
DEF_INST(subtract_decimal)1253 DEF_INST(subtract_decimal)
1254 {
1255 int     l1, l2;                         /* Length values             */
1256 int     b1, b2;                         /* Base register numbers     */
1257 VADR    effective_addr1,
1258         effective_addr2;                /* Effective addresses       */
1259 int     cc;                             /* Condition code            */
1260 BYTE    dec1[MAX_DECIMAL_DIGITS];       /* Work area for operand 1   */
1261 BYTE    dec2[MAX_DECIMAL_DIGITS];       /* Work area for operand 2   */
1262 BYTE    dec3[MAX_DECIMAL_DIGITS];       /* Work area for result      */
1263 int     count1, count2, count3;         /* Significant digit counters*/
1264 int     sign1, sign2, sign3;            /* Sign of operands & result */
1265 
1266     SS(inst, regs, l1, l2, b1, effective_addr1,
1267                                      b2, effective_addr2);
1268 
1269     /* Load operands into work areas */
1270     ARCH_DEP(load_decimal) (effective_addr1, l1, b1, regs, dec1, &count1, &sign1);
1271     ARCH_DEP(load_decimal) (effective_addr2, l2, b2, regs, dec2, &count2, &sign2);
1272 
1273     /* Add or subtract operand values */
1274     if (count2 == 0)
1275     {
1276         /* If second operand is zero then result is first operand */
1277         memcpy (dec3, dec1, MAX_DECIMAL_DIGITS);
1278         count3 = count1;
1279         sign3 = sign1;
1280     }
1281     else if (count1 == 0)
1282     {
1283         /* If first operand is zero then result is -second operand */
1284         memcpy (dec3, dec2, MAX_DECIMAL_DIGITS);
1285         count3 = count2;
1286         sign3 = -sign2;
1287     }
1288     else if (sign1 != sign2)
1289     {
1290         /* If signs are opposite then add operands */
1291         add_decimal (dec1, dec2, dec3, &count3);
1292         sign3 = sign1;
1293     }
1294     else
1295     {
1296         /* If signs are equal then subtract operands */
1297         subtract_decimal (dec1, dec2, dec3, &count3, &sign3);
1298         if (sign1 < 0) sign3 = -sign3;
1299     }
1300 
1301     /* Set condition code */
1302     cc = (count3 == 0) ? 0 : (sign3 < 1) ? 1 : 2;
1303 
1304     /* Overflow if result exceeds first operand length */
1305     if (count3 > (l1+1) * 2 - 1)
1306         cc = 3;
1307 
1308     /* Set positive sign if result is zero */
1309     if (count3 == 0)
1310         sign3 = 1;
1311 
1312     /* Store result into first operand location */
1313     ARCH_DEP(store_decimal) (effective_addr1, l1, b1, regs, dec3, sign3);
1314 
1315     /* Return condition code */
1316     regs->psw.cc = cc;
1317 
1318     /* Program check if overflow and PSW program mask is set */
1319     if (cc == 3 && DOMASK(&regs->psw))
1320         ARCH_DEP(program_interrupt) (regs, PGM_DECIMAL_OVERFLOW_EXCEPTION);
1321 
1322 } /* end DEF_INST(subtract_decimal) */
1323 
1324 
1325 /*-------------------------------------------------------------------*/
1326 /* F8   ZAP   - Zero and Add                                    [SS] */
1327 /*-------------------------------------------------------------------*/
DEF_INST(zero_and_add)1328 DEF_INST(zero_and_add)
1329 {
1330 int     l1, l2;                         /* Length values             */
1331 int     b1, b2;                         /* Base register numbers     */
1332 VADR    effective_addr1,
1333         effective_addr2;                /* Effective addresses       */
1334 int     cc;                             /* Condition code            */
1335 BYTE    dec[MAX_DECIMAL_DIGITS];        /* Work area for operand     */
1336 int     count;                          /* Significant digit counter */
1337 int     sign;                           /* Sign                      */
1338 
1339     SS(inst, regs, l1, l2, b1, effective_addr1,
1340                                      b2, effective_addr2);
1341 
1342     /* Load second operand into work area */
1343     ARCH_DEP(load_decimal) (effective_addr2, l2, b2, regs, dec, &count, &sign);
1344 
1345     /* Set condition code */
1346     cc = (count == 0) ? 0 : (sign < 1) ? 1 : 2;
1347 
1348     /* Overflow if result exceeds first operand length */
1349     if (count > (l1+1) * 2 - 1)
1350         cc = 3;
1351 
1352     /* Set positive sign if result is zero */
1353     if (count == 0)
1354         sign = +1;
1355 
1356     /* Store result into first operand location */
1357     ARCH_DEP(store_decimal) (effective_addr1, l1, b1, regs, dec, sign);
1358 
1359     /* Return condition code */
1360     regs->psw.cc = cc;
1361 
1362     /* Program check if overflow and PSW program mask is set */
1363     if (cc == 3 && DOMASK(&regs->psw))
1364         ARCH_DEP(program_interrupt) (regs, PGM_DECIMAL_OVERFLOW_EXCEPTION);
1365 
1366 } /* end DEF_INST(zero_and_add) */
1367 
1368 
1369 #if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)
1370 /*-------------------------------------------------------------------*/
1371 /* EBC0 TP    - Test Decimal                                   [RSL] */
1372 /*-------------------------------------------------------------------*/
DEF_INST(test_decimal)1373 DEF_INST(test_decimal)
1374 {
1375 int     l1;                             /* Length value              */
1376 int     b1;                             /* Base register number      */
1377 VADR    effective_addr1;                /* Effective address         */
1378 int     i;                              /* Array subscript           */
1379 int     cc = 0;                         /* Condition code            */
1380 BYTE    pack[MAX_DECIMAL_LENGTH];       /* Packed decimal work area  */
1381 
1382     RSL(inst, regs, l1, b1, effective_addr1);
1383 
1384     /* Fetch the packed decimal operand into the work area */
1385     ARCH_DEP(vfetchc) (pack, l1, effective_addr1, b1, regs);
1386 
1387     /* Test each byte of the operand */
1388     for (i=0; ; i++)
1389     {
1390         /* Test the high-order digit of the byte */
1391         if ((pack[i] & 0xF0) > 0x90)
1392             cc = 2;
1393 
1394         /* Exit if this is the last byte */
1395         if (i == l1) break;
1396 
1397         /* Test the low-order digit of the byte */
1398         if ((pack[i] & 0x0F) > 0x09)
1399             cc = 2;
1400     }
1401 
1402     /* Test the sign in the last byte */
1403     if ((pack[i] & 0x0F) < 0x0A)
1404         cc |= 1;
1405 
1406     /* Return condition code */
1407     regs->psw.cc = cc;
1408 
1409 } /* end DEF_INST(test_decimal) */
1410 #endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/
1411 
1412 
1413 #if !defined(_GEN_ARCH)
1414 
1415 #if defined(_ARCHMODE2)
1416  #define  _GEN_ARCH _ARCHMODE2
1417  #include "decimal.c"
1418 #endif
1419 
1420 #if defined(_ARCHMODE3)
1421  #undef   _GEN_ARCH
1422  #define  _GEN_ARCH _ARCHMODE3
1423  #include "decimal.c"
1424 #endif
1425 
1426 #endif /*!defined(_GEN_ARCH)*/
1427