Upgrade GDB from 7.4.1 to 7.6.1 on the vendor branch
[dragonfly.git] / contrib / gdb-7 / libdecnumber / dpd / decimal128.c
1 /* Decimal 128-bit format module for the decNumber C Library.
2    Copyright (C) 2005-2013 Free Software Foundation, Inc.
3    Contributed by IBM Corporation.  Author Mike Cowlishaw.
4
5    This file is part of GCC.
6
7    GCC is free software; you can redistribute it and/or modify it under
8    the terms of the GNU General Public License as published by the Free
9    Software Foundation; either version 3, or (at your option) any later
10    version.
11
12    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13    WARRANTY; without even the implied warranty of MERCHANTABILITY or
14    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15    for more details.
16
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
20
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 <http://www.gnu.org/licenses/>.  */
25
26 /* ------------------------------------------------------------------ */
27 /* Decimal 128-bit format module                                      */
28 /* ------------------------------------------------------------------ */
29 /* This module comprises the routines for decimal128 format numbers.  */
30 /* Conversions are supplied to and from decNumber and String.         */
31 /*                                                                    */
32 /* This is used when decNumber provides operations, either for all    */
33 /* operations or as a proxy between decNumber and decSingle.          */
34 /*                                                                    */
35 /* Error handling is the same as decNumber (qv.).                     */
36 /* ------------------------------------------------------------------ */
37 #include <string.h>           /* [for memset/memcpy] */
38 #include <stdio.h>            /* [for printf] */
39
40 #include "dconfig.h"          /* GCC definitions */
41 #define  DECNUMDIGITS 34      /* make decNumbers with space for 34 */
42 #include "decNumber.h"        /* base number library */
43 #include "decNumberLocal.h"   /* decNumber local types, etc. */
44 #include "decimal128.h"       /* our primary include */
45
46 /* Utility routines and tables [in decimal64.c] */
47 extern const uInt   COMBEXP[32], COMBMSD[32];
48 extern const uShort DPD2BIN[1024];
49 extern const uShort BIN2DPD[1000];      /* [not used] */
50 extern const uByte  BIN2CHAR[4001];
51
52 extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
53 extern void decDigitsToDPD(const decNumber *, uInt *, Int);
54
55 #if DECTRACE || DECCHECK
56 void decimal128Show(const decimal128 *);          /* for debug */
57 extern void decNumberShow(const decNumber *);     /* .. */
58 #endif
59
60 /* Useful macro */
61 /* Clear a structure (e.g., a decNumber) */
62 #define DEC_clear(d) memset(d, 0, sizeof(*d))
63
64 /* ------------------------------------------------------------------ */
65 /* decimal128FromNumber -- convert decNumber to decimal128            */
66 /*                                                                    */
67 /*   ds is the target decimal128                                      */
68 /*   dn is the source number (assumed valid)                          */
69 /*   set is the context, used only for reporting errors               */
70 /*                                                                    */
71 /* The set argument is used only for status reporting and for the     */
72 /* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/
73 /* digits or an overflow is detected).  If the exponent is out of the */
74 /* valid range then Overflow or Underflow will be raised.             */
75 /* After Underflow a subnormal result is possible.                    */
76 /*                                                                    */
77 /* DEC_Clamped is set if the number has to be 'folded down' to fit,   */
78 /* by reducing its exponent and multiplying the coefficient by a      */
79 /* power of ten, or if the exponent on a zero had to be clamped.      */
80 /* ------------------------------------------------------------------ */
81 decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
82                                   decContext *set) {
83   uInt status=0;                   /* status accumulator */
84   Int ae;                          /* adjusted exponent */
85   decNumber  dw;                   /* work */
86   decContext dc;                   /* .. */
87   uInt comb, exp;                  /* .. */
88   uInt uiwork;                     /* for macros */
89   uInt targar[4]={0,0,0,0};        /* target 128-bit */
90   #define targhi targar[3]         /* name the word with the sign */
91   #define targmh targar[2]         /* name the words */
92   #define targml targar[1]         /* .. */
93   #define targlo targar[0]         /* .. */
94
95   /* If the number has too many digits, or the exponent could be */
96   /* out of range then reduce the number under the appropriate */
97   /* constraints.  This could push the number to Infinity or zero, */
98   /* so this check and rounding must be done before generating the */
99   /* decimal128] */
100   ae=dn->exponent+dn->digits-1;              /* [0 if special] */
101   if (dn->digits>DECIMAL128_Pmax             /* too many digits */
102    || ae>DECIMAL128_Emax                     /* likely overflow */
103    || ae<DECIMAL128_Emin) {                  /* likely underflow */
104     decContextDefault(&dc, DEC_INIT_DECIMAL128); /* [no traps] */
105     dc.round=set->round;                     /* use supplied rounding */
106     decNumberPlus(&dw, dn, &dc);             /* (round and check) */
107     /* [this changes -0 to 0, so enforce the sign...] */
108     dw.bits|=dn->bits&DECNEG;
109     status=dc.status;                        /* save status */
110     dn=&dw;                                  /* use the work number */
111     } /* maybe out of range */
112
113   if (dn->bits&DECSPECIAL) {                      /* a special value */
114     if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
115      else {                                       /* sNaN or qNaN */
116       if ((*dn->lsu!=0 || dn->digits>1)           /* non-zero coefficient */
117        && (dn->digits<DECIMAL128_Pmax)) {         /* coefficient fits */
118         decDigitsToDPD(dn, targar, 0);
119         }
120       if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
121        else targhi|=DECIMAL_sNaN<<24;
122       } /* a NaN */
123     } /* special */
124
125    else { /* is finite */
126     if (decNumberIsZero(dn)) {               /* is a zero */
127       /* set and clamp exponent */
128       if (dn->exponent<-DECIMAL128_Bias) {
129         exp=0;                               /* low clamp */
130         status|=DEC_Clamped;
131         }
132        else {
133         exp=dn->exponent+DECIMAL128_Bias;    /* bias exponent */
134         if (exp>DECIMAL128_Ehigh) {          /* top clamp */
135           exp=DECIMAL128_Ehigh;
136           status|=DEC_Clamped;
137           }
138         }
139       comb=(exp>>9) & 0x18;             /* msd=0, exp top 2 bits .. */
140       }
141      else {                             /* non-zero finite number */
142       uInt msd;                         /* work */
143       Int pad=0;                        /* coefficient pad digits */
144
145       /* the dn is known to fit, but it may need to be padded */
146       exp=(uInt)(dn->exponent+DECIMAL128_Bias);    /* bias exponent */
147       if (exp>DECIMAL128_Ehigh) {                  /* fold-down case */
148         pad=exp-DECIMAL128_Ehigh;
149         exp=DECIMAL128_Ehigh;                      /* [to maximum] */
150         status|=DEC_Clamped;
151         }
152
153       /* [fastpath for common case is not a win, here] */
154       decDigitsToDPD(dn, targar, pad);
155       /* save and clear the top digit */
156       msd=targhi>>14;
157       targhi&=0x00003fff;
158
159       /* create the combination field */
160       if (msd>=8) comb=0x18 | ((exp>>11) & 0x06) | (msd & 0x01);
161              else comb=((exp>>9) & 0x18) | msd;
162       }
163     targhi|=comb<<26;              /* add combination field .. */
164     targhi|=(exp&0xfff)<<14;       /* .. and exponent continuation */
165     } /* finite */
166
167   if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */
168
169   /* now write to storage; this is endian */
170   if (DECLITEND) {
171     /* lo -> hi */
172     UBFROMUI(d128->bytes,    targlo);
173     UBFROMUI(d128->bytes+4,  targml);
174     UBFROMUI(d128->bytes+8,  targmh);
175     UBFROMUI(d128->bytes+12, targhi);
176     }
177    else {
178     /* hi -> lo */
179     UBFROMUI(d128->bytes,    targhi);
180     UBFROMUI(d128->bytes+4,  targmh);
181     UBFROMUI(d128->bytes+8,  targml);
182     UBFROMUI(d128->bytes+12, targlo);
183     }
184
185   if (status!=0) decContextSetStatus(set, status); /* pass on status */
186   /* decimal128Show(d128); */
187   return d128;
188   } /* decimal128FromNumber */
189
190 /* ------------------------------------------------------------------ */
191 /* decimal128ToNumber -- convert decimal128 to decNumber              */
192 /*   d128 is the source decimal128                                    */
193 /*   dn is the target number, with appropriate space                  */
194 /* No error is possible.                                              */
195 /* ------------------------------------------------------------------ */
196 decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
197   uInt msd;                        /* coefficient MSD */
198   uInt exp;                        /* exponent top two bits */
199   uInt comb;                       /* combination field */
200   Int  need;                       /* work */
201   uInt uiwork;                     /* for macros */
202   uInt sourar[4];                  /* source 128-bit */
203   #define sourhi sourar[3]         /* name the word with the sign */
204   #define sourmh sourar[2]         /* and the mid-high word */
205   #define sourml sourar[1]         /* and the mod-low word */
206   #define sourlo sourar[0]         /* and the lowest word */
207
208   /* load source from storage; this is endian */
209   if (DECLITEND) {
210     sourlo=UBTOUI(d128->bytes   ); /* directly load the low int */
211     sourml=UBTOUI(d128->bytes+4 ); /* then the mid-low */
212     sourmh=UBTOUI(d128->bytes+8 ); /* then the mid-high */
213     sourhi=UBTOUI(d128->bytes+12); /* then the high int */
214     }
215    else {
216     sourhi=UBTOUI(d128->bytes   ); /* directly load the high int */
217     sourmh=UBTOUI(d128->bytes+4 ); /* then the mid-high */
218     sourml=UBTOUI(d128->bytes+8 ); /* then the mid-low */
219     sourlo=UBTOUI(d128->bytes+12); /* then the low int */
220     }
221
222   comb=(sourhi>>26)&0x1f;          /* combination field */
223
224   decNumberZero(dn);               /* clean number */
225   if (sourhi&0x80000000) dn->bits=DECNEG; /* set sign if negative */
226
227   msd=COMBMSD[comb];               /* decode the combination field */
228   exp=COMBEXP[comb];               /* .. */
229
230   if (exp==3) {                    /* is a special */
231     if (msd==0) {
232       dn->bits|=DECINF;
233       return dn;                   /* no coefficient needed */
234       }
235     else if (sourhi&0x02000000) dn->bits|=DECSNAN;
236     else dn->bits|=DECNAN;
237     msd=0;                         /* no top digit */
238     }
239    else {                          /* is a finite number */
240     dn->exponent=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */
241     }
242
243   /* get the coefficient */
244   sourhi&=0x00003fff;              /* clean coefficient continuation */
245   if (msd) {                       /* non-zero msd */
246     sourhi|=msd<<14;               /* prefix to coefficient */
247     need=12;                       /* process 12 declets */
248     }
249    else { /* msd=0 */
250     if (sourhi) need=11;           /* declets to process */
251      else if (sourmh) need=10;
252      else if (sourml) need=7;
253      else if (sourlo) need=4;
254      else return dn;               /* easy: coefficient is 0 */
255     } /*msd=0 */
256
257   decDigitsFromDPD(dn, sourar, need);   /* process declets */
258   /* decNumberShow(dn); */
259   return dn;
260   } /* decimal128ToNumber */
261
262 /* ------------------------------------------------------------------ */
263 /* to-scientific-string -- conversion to numeric string               */
264 /* to-engineering-string -- conversion to numeric string              */
265 /*                                                                    */
266 /*   decimal128ToString(d128, string);                                */
267 /*   decimal128ToEngString(d128, string);                             */
268 /*                                                                    */
269 /*  d128 is the decimal128 format number to convert                   */
270 /*  string is the string where the result will be laid out            */
271 /*                                                                    */
272 /*  string must be at least 24 characters                             */
273 /*                                                                    */
274 /*  No error is possible, and no status can be set.                   */
275 /* ------------------------------------------------------------------ */
276 char * decimal128ToEngString(const decimal128 *d128, char *string){
277   decNumber dn;                         /* work */
278   decimal128ToNumber(d128, &dn);
279   decNumberToEngString(&dn, string);
280   return string;
281   } /* decimal128ToEngString */
282
283 char * decimal128ToString(const decimal128 *d128, char *string){
284   uInt msd;                        /* coefficient MSD */
285   Int  exp;                        /* exponent top two bits or full */
286   uInt comb;                       /* combination field */
287   char *cstart;                    /* coefficient start */
288   char *c;                         /* output pointer in string */
289   const uByte *u;                  /* work */
290   char *s, *t;                     /* .. (source, target) */
291   Int  dpd;                        /* .. */
292   Int  pre, e;                     /* .. */
293   uInt uiwork;                     /* for macros */
294
295   uInt sourar[4];                  /* source 128-bit */
296   #define sourhi sourar[3]         /* name the word with the sign */
297   #define sourmh sourar[2]         /* and the mid-high word */
298   #define sourml sourar[1]         /* and the mod-low word */
299   #define sourlo sourar[0]         /* and the lowest word */
300
301   /* load source from storage; this is endian */
302   if (DECLITEND) {
303     sourlo=UBTOUI(d128->bytes   ); /* directly load the low int */
304     sourml=UBTOUI(d128->bytes+4 ); /* then the mid-low */
305     sourmh=UBTOUI(d128->bytes+8 ); /* then the mid-high */
306     sourhi=UBTOUI(d128->bytes+12); /* then the high int */
307     }
308    else {
309     sourhi=UBTOUI(d128->bytes   ); /* directly load the high int */
310     sourmh=UBTOUI(d128->bytes+4 ); /* then the mid-high */
311     sourml=UBTOUI(d128->bytes+8 ); /* then the mid-low */
312     sourlo=UBTOUI(d128->bytes+12); /* then the low int */
313     }
314
315   c=string;                        /* where result will go */
316   if (((Int)sourhi)<0) *c++='-';   /* handle sign */
317
318   comb=(sourhi>>26)&0x1f;          /* combination field */
319   msd=COMBMSD[comb];               /* decode the combination field */
320   exp=COMBEXP[comb];               /* .. */
321
322   if (exp==3) {
323     if (msd==0) {                  /* infinity */
324       strcpy(c,   "Inf");
325       strcpy(c+3, "inity");
326       return string;               /* easy */
327       }
328     if (sourhi&0x02000000) *c++='s'; /* sNaN */
329     strcpy(c, "NaN");              /* complete word */
330     c+=3;                          /* step past */
331     if (sourlo==0 && sourml==0 && sourmh==0
332      && (sourhi&0x0003ffff)==0) return string; /* zero payload */
333     /* otherwise drop through to add integer; set correct exp */
334     exp=0; msd=0;                  /* setup for following code */
335     }
336    else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */
337
338   /* convert 34 digits of significand to characters */
339   cstart=c;                        /* save start of coefficient */
340   if (msd) *c++='0'+(char)msd;     /* non-zero most significant digit */
341
342   /* Now decode the declets.  After extracting each one, it is */
343   /* decoded to binary and then to a 4-char sequence by table lookup; */
344   /* the 4-chars are a 1-char length (significant digits, except 000 */
345   /* has length 0).  This allows us to left-align the first declet */
346   /* with non-zero content, then remaining ones are full 3-char */
347   /* length.  We use fixed-length memcpys because variable-length */
348   /* causes a subroutine call in GCC.  (These are length 4 for speed */
349   /* and are safe because the array has an extra terminator byte.) */
350   #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4];                   \
351                    if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}      \
352                     else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
353   dpd=(sourhi>>4)&0x3ff;                     /* declet 1 */
354   dpd2char;
355   dpd=((sourhi&0xf)<<6) | (sourmh>>26);      /* declet 2 */
356   dpd2char;
357   dpd=(sourmh>>16)&0x3ff;                    /* declet 3 */
358   dpd2char;
359   dpd=(sourmh>>6)&0x3ff;                     /* declet 4 */
360   dpd2char;
361   dpd=((sourmh&0x3f)<<4) | (sourml>>28);     /* declet 5 */
362   dpd2char;
363   dpd=(sourml>>18)&0x3ff;                    /* declet 6 */
364   dpd2char;
365   dpd=(sourml>>8)&0x3ff;                     /* declet 7 */
366   dpd2char;
367   dpd=((sourml&0xff)<<2) | (sourlo>>30);     /* declet 8 */
368   dpd2char;
369   dpd=(sourlo>>20)&0x3ff;                    /* declet 9 */
370   dpd2char;
371   dpd=(sourlo>>10)&0x3ff;                    /* declet 10 */
372   dpd2char;
373   dpd=(sourlo)&0x3ff;                        /* declet 11 */
374   dpd2char;
375
376   if (c==cstart) *c++='0';         /* all zeros -- make 0 */
377
378   if (exp==0) {                    /* integer or NaN case -- easy */
379     *c='\0';                       /* terminate */
380     return string;
381     }
382
383   /* non-0 exponent */
384   e=0;                             /* assume no E */
385   pre=c-cstart+exp;
386   /* [here, pre-exp is the digits count (==1 for zero)] */
387   if (exp>0 || pre<-5) {           /* need exponential form */
388     e=pre-1;                       /* calculate E value */
389     pre=1;                         /* assume one digit before '.' */
390     } /* exponential form */
391
392   /* modify the coefficient, adding 0s, '.', and E+nn as needed */
393   s=c-1;                           /* source (LSD) */
394   if (pre>0) {                     /* ddd.ddd (plain), perhaps with E */
395     char *dotat=cstart+pre;
396     if (dotat<c) {                 /* if embedded dot needed... */
397       t=c;                              /* target */
398       for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */
399       *t='.';                           /* insert the dot */
400       c++;                              /* length increased by one */
401       }
402
403     /* finally add the E-part, if needed; it will never be 0, and has */
404     /* a maximum length of 4 digits */
405     if (e!=0) {
406       *c++='E';                    /* starts with E */
407       *c++='+';                    /* assume positive */
408       if (e<0) {
409         *(c-1)='-';                /* oops, need '-' */
410         e=-e;                      /* uInt, please */
411         }
412       if (e<1000) {                /* 3 (or fewer) digits case */
413         u=&BIN2CHAR[e*4];          /* -> length byte */
414         memcpy(c, u+4-*u, 4);      /* copy fixed 4 characters [is safe] */
415         c+=*u;                     /* bump pointer appropriately */
416         }
417        else {                      /* 4-digits */
418         Int thou=((e>>3)*1049)>>17; /* e/1000 */
419         Int rem=e-(1000*thou);      /* e%1000 */
420         *c++='0'+(char)thou;
421         u=&BIN2CHAR[rem*4];        /* -> length byte */
422         memcpy(c, u+1, 4);         /* copy fixed 3+1 characters [is safe] */
423         c+=3;                      /* bump pointer, always 3 digits */
424         }
425       }
426     *c='\0';                       /* add terminator */
427     /*printf("res %s\n", string); */
428     return string;
429     } /* pre>0 */
430
431   /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
432   t=c+1-pre;
433   *(t+1)='\0';                          /* can add terminator now */
434   for (; s>=cstart; s--, t--) *t=*s;    /* shift whole coefficient right */
435   c=cstart;
436   *c++='0';                             /* always starts with 0. */
437   *c++='.';
438   for (; pre<0; pre++) *c++='0';        /* add any 0's after '.' */
439   /*printf("res %s\n", string); */
440   return string;
441   } /* decimal128ToString */
442
443 /* ------------------------------------------------------------------ */
444 /* to-number -- conversion from numeric string                        */
445 /*                                                                    */
446 /*   decimal128FromString(result, string, set);                       */
447 /*                                                                    */
448 /*  result  is the decimal128 format number which gets the result of  */
449 /*          the conversion                                            */
450 /*  *string is the character string which should contain a valid      */
451 /*          number (which may be a special value)                     */
452 /*  set     is the context                                            */
453 /*                                                                    */
454 /* The context is supplied to this routine is used for error handling */
455 /* (setting of status and traps) and for the rounding mode, only.     */
456 /* If an error occurs, the result will be a valid decimal128 NaN.     */
457 /* ------------------------------------------------------------------ */
458 decimal128 * decimal128FromString(decimal128 *result, const char *string,
459                                   decContext *set) {
460   decContext dc;                             /* work */
461   decNumber dn;                              /* .. */
462
463   decContextDefault(&dc, DEC_INIT_DECIMAL128); /* no traps, please */
464   dc.round=set->round;                         /* use supplied rounding */
465
466   decNumberFromString(&dn, string, &dc);     /* will round if needed */
467   decimal128FromNumber(result, &dn, &dc);
468   if (dc.status!=0) {                        /* something happened */
469     decContextSetStatus(set, dc.status);     /* .. pass it on */
470     }
471   return result;
472   } /* decimal128FromString */
473
474 /* ------------------------------------------------------------------ */
475 /* decimal128IsCanonical -- test whether encoding is canonical        */
476 /*   d128 is the source decimal128                                    */
477 /*   returns 1 if the encoding of d128 is canonical, 0 otherwise      */
478 /* No error is possible.                                              */
479 /* ------------------------------------------------------------------ */
480 uInt decimal128IsCanonical(const decimal128 *d128) {
481   decNumber dn;                         /* work */
482   decimal128 canon;                      /* .. */
483   decContext dc;                        /* .. */
484   decContextDefault(&dc, DEC_INIT_DECIMAL128);
485   decimal128ToNumber(d128, &dn);
486   decimal128FromNumber(&canon, &dn, &dc);/* canon will now be canonical */
487   return memcmp(d128, &canon, DECIMAL128_Bytes)==0;
488   } /* decimal128IsCanonical */
489
490 /* ------------------------------------------------------------------ */
491 /* decimal128Canonical -- copy an encoding, ensuring it is canonical  */
492 /*   d128 is the source decimal128                                    */
493 /*   result is the target (may be the same decimal128)                */
494 /*   returns result                                                   */
495 /* No error is possible.                                              */
496 /* ------------------------------------------------------------------ */
497 decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) {
498   decNumber dn;                         /* work */
499   decContext dc;                        /* .. */
500   decContextDefault(&dc, DEC_INIT_DECIMAL128);
501   decimal128ToNumber(d128, &dn);
502   decimal128FromNumber(result, &dn, &dc);/* result will now be canonical */
503   return result;
504   } /* decimal128Canonical */
505
506 #if DECTRACE || DECCHECK
507 /* Macros for accessing decimal128 fields.  These assume the argument
508    is a reference (pointer) to the decimal128 structure, and the
509    decimal128 is in network byte order (big-endian) */
510 /* Get sign */
511 #define decimal128Sign(d)       ((unsigned)(d)->bytes[0]>>7)
512
513 /* Get combination field */
514 #define decimal128Comb(d)       (((d)->bytes[0] & 0x7c)>>2)
515
516 /* Get exponent continuation [does not remove bias] */
517 #define decimal128ExpCon(d)     ((((d)->bytes[0] & 0x03)<<10)         \
518                               | ((unsigned)(d)->bytes[1]<<2)          \
519                               | ((unsigned)(d)->bytes[2]>>6))
520
521 /* Set sign [this assumes sign previously 0] */
522 #define decimal128SetSign(d, b) {                                     \
523   (d)->bytes[0]|=((unsigned)(b)<<7);}
524
525 /* Set exponent continuation [does not apply bias] */
526 /* This assumes range has been checked and exponent previously 0; */
527 /* type of exponent must be unsigned */
528 #define decimal128SetExpCon(d, e) {                                   \
529   (d)->bytes[0]|=(uByte)((e)>>10);                                    \
530   (d)->bytes[1] =(uByte)(((e)&0x3fc)>>2);                             \
531   (d)->bytes[2]|=(uByte)(((e)&0x03)<<6);}
532
533 /* ------------------------------------------------------------------ */
534 /* decimal128Show -- display a decimal128 in hexadecimal [debug aid]  */
535 /*   d128 -- the number to show                                       */
536 /* ------------------------------------------------------------------ */
537 /* Also shows sign/cob/expconfields extracted */
538 void decimal128Show(const decimal128 *d128) {
539   char buf[DECIMAL128_Bytes*2+1];
540   Int i, j=0;
541
542   if (DECLITEND) {
543     for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
544       sprintf(&buf[j], "%02x", d128->bytes[15-i]);
545       }
546     printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
547            d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f,
548            ((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)|
549            (d128->bytes[13]>>6));
550     }
551    else {
552     for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
553       sprintf(&buf[j], "%02x", d128->bytes[i]);
554       }
555     printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
556            decimal128Sign(d128), decimal128Comb(d128),
557            decimal128ExpCon(d128));
558     }
559   } /* decimal128Show */
560 #endif