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