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