cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

decimal32.c (19416B)


      1/* Decimal 32-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 32-bit format module					      */
     33/* ------------------------------------------------------------------ */
     34/* This module comprises the routines for decimal32 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  7      /* make decNumbers with space for 7 */
     46#include "libdecnumber/decNumber.h"
     47#include "libdecnumber/decNumberLocal.h"
     48#include "libdecnumber/dpd/decimal32.h"
     49
     50/* Utility tables and routines [in decimal64.c] */
     51extern const uInt   COMBEXP[32], COMBMSD[32];
     52extern const uByte  BIN2CHAR[4001];
     53
     54extern void decDigitsToDPD(const decNumber *, uInt *, Int);
     55extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
     56
     57#if DECTRACE || DECCHECK
     58void decimal32Show(const decimal32 *);		  /* for debug */
     59extern 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/* decimal32FromNumber -- convert decNumber to decimal32	      */
     68/*								      */
     69/*   ds is the target decimal32					      */
     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 DECIMAL32_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/* ------------------------------------------------------------------ */
     83decimal32 * decimal32FromNumber(decimal32 *d32, 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 targ=0;			   /* target 32-bit */
     92
     93  /* If the number has too many digits, or the exponent could be */
     94  /* out of range then reduce the number under the appropriate */
     95  /* constraints.  This could push the number to Infinity or zero, */
     96  /* so this check and rounding must be done before generating the */
     97  /* decimal32] */
     98  ae=dn->exponent+dn->digits-1;		     /* [0 if special] */
     99  if (dn->digits>DECIMAL32_Pmax		     /* too many digits */
    100   || ae>DECIMAL32_Emax			     /* likely overflow */
    101   || ae<DECIMAL32_Emin) {		     /* likely underflow */
    102    decContextDefault(&dc, DEC_INIT_DECIMAL32); /* [no traps] */
    103    dc.round=set->round;		     /* use supplied rounding */
    104    decNumberPlus(&dw, dn, &dc);	     /* (round and check) */
    105    /* [this changes -0 to 0, so enforce the sign...] */
    106    dw.bits|=dn->bits&DECNEG;
    107    status=dc.status;			     /* save status */
    108    dn=&dw;				     /* use the work number */
    109    } /* maybe out of range */
    110
    111  if (dn->bits&DECSPECIAL) {			  /* a special value */
    112    if (dn->bits&DECINF) targ=DECIMAL_Inf<<24;
    113     else {					  /* sNaN or qNaN */
    114      if ((*dn->lsu!=0 || dn->digits>1)		  /* non-zero coefficient */
    115       && (dn->digits<DECIMAL32_Pmax)) {	  /* coefficient fits */
    116	decDigitsToDPD(dn, &targ, 0);
    117	}
    118      if (dn->bits&DECNAN) targ|=DECIMAL_NaN<<24;
    119       else targ|=DECIMAL_sNaN<<24;
    120      } /* a NaN */
    121    } /* special */
    122
    123   else { /* is finite */
    124    if (decNumberIsZero(dn)) {		     /* is a zero */
    125      /* set and clamp exponent */
    126      if (dn->exponent<-DECIMAL32_Bias) {
    127	exp=0;				     /* low clamp */
    128	status|=DEC_Clamped;
    129	}
    130       else {
    131	exp=dn->exponent+DECIMAL32_Bias;     /* bias exponent */
    132	if (exp>DECIMAL32_Ehigh) {	     /* top clamp */
    133	  exp=DECIMAL32_Ehigh;
    134	  status|=DEC_Clamped;
    135	  }
    136	}
    137      comb=(exp>>3) & 0x18;		/* msd=0, exp top 2 bits .. */
    138      }
    139     else {				/* non-zero finite number */
    140      uInt msd;				/* work */
    141      Int pad=0;			/* coefficient pad digits */
    142
    143      /* the dn is known to fit, but it may need to be padded */
    144      exp=(uInt)(dn->exponent+DECIMAL32_Bias);	  /* bias exponent */
    145      if (exp>DECIMAL32_Ehigh) {		  /* fold-down case */
    146	pad=exp-DECIMAL32_Ehigh;
    147	exp=DECIMAL32_Ehigh;			  /* [to maximum] */
    148	status|=DEC_Clamped;
    149	}
    150
    151      /* fastpath common case */
    152      if (DECDPUN==3 && pad==0) {
    153	targ=BIN2DPD[dn->lsu[0]];
    154	if (dn->digits>3) targ|=(uInt)(BIN2DPD[dn->lsu[1]])<<10;
    155	msd=(dn->digits==7 ? dn->lsu[2] : 0);
    156	}
    157       else { /* general case */
    158	decDigitsToDPD(dn, &targ, pad);
    159	/* save and clear the top digit */
    160	msd=targ>>20;
    161	targ&=0x000fffff;
    162	}
    163
    164      /* create the combination field */
    165      if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01);
    166	     else comb=((exp>>3) & 0x18) | msd;
    167      }
    168    targ|=comb<<26;		   /* add combination field .. */
    169    targ|=(exp&0x3f)<<20;	   /* .. and exponent continuation */
    170    } /* finite */
    171
    172  if (dn->bits&DECNEG) targ|=0x80000000;  /* add sign bit */
    173
    174  /* now write to storage; this is endian */
    175  pu=(uInt *)d32->bytes;	   /* overlay */
    176  *pu=targ;			   /* directly store the int */
    177
    178  if (status!=0) decContextSetStatus(set, status); /* pass on status */
    179  /* decimal32Show(d32); */
    180  return d32;
    181  } /* decimal32FromNumber */
    182
    183/* ------------------------------------------------------------------ */
    184/* decimal32ToNumber -- convert decimal32 to decNumber		      */
    185/*   d32 is the source decimal32				      */
    186/*   dn is the target number, with appropriate space		      */
    187/* No error is possible.					      */
    188/* ------------------------------------------------------------------ */
    189decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
    190  uInt msd;			   /* coefficient MSD */
    191  uInt exp;			   /* exponent top two bits */
    192  uInt comb;			   /* combination field */
    193  uInt sour;			   /* source 32-bit */
    194  const uInt *pu;		   /* work */
    195
    196  /* load source from storage; this is endian */
    197  pu=(const uInt *)d32->bytes;	   /* overlay */
    198  sour=*pu;			   /* directly load the int */
    199
    200  comb=(sour>>26)&0x1f;		   /* combination field */
    201
    202  decNumberZero(dn);		   /* clean number */
    203  if (sour&0x80000000) dn->bits=DECNEG; /* set sign if negative */
    204
    205  msd=COMBMSD[comb];		   /* decode the combination field */
    206  exp=COMBEXP[comb];		   /* .. */
    207
    208  if (exp==3) {			   /* is a special */
    209    if (msd==0) {
    210      dn->bits|=DECINF;
    211      return dn;		   /* no coefficient needed */
    212      }
    213    else if (sour&0x02000000) dn->bits|=DECSNAN;
    214    else dn->bits|=DECNAN;
    215    msd=0;			   /* no top digit */
    216    }
    217   else {			   /* is a finite number */
    218    dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */
    219    }
    220
    221  /* get the coefficient */
    222  sour&=0x000fffff;		   /* clean coefficient continuation */
    223  if (msd) {			   /* non-zero msd */
    224    sour|=msd<<20;		   /* prefix to coefficient */
    225    decDigitsFromDPD(dn, &sour, 3); /* process 3 declets */
    226    return dn;
    227    }
    228  /* msd=0 */
    229  if (!sour) return dn;		   /* easy: coefficient is 0 */
    230  if (sour&0x000ffc00)		   /* need 2 declets? */
    231    decDigitsFromDPD(dn, &sour, 2); /* process 2 declets */
    232   else
    233    decDigitsFromDPD(dn, &sour, 1); /* process 1 declet */
    234  return dn;
    235  } /* decimal32ToNumber */
    236
    237/* ------------------------------------------------------------------ */
    238/* to-scientific-string -- conversion to numeric string		      */
    239/* to-engineering-string -- conversion to numeric string	      */
    240/*								      */
    241/*   decimal32ToString(d32, string);				      */
    242/*   decimal32ToEngString(d32, string);				      */
    243/*								      */
    244/*  d32 is the decimal32 format number to convert		      */
    245/*  string is the string where the result will be laid out	      */
    246/*								      */
    247/*  string must be at least 24 characters			      */
    248/*								      */
    249/*  No error is possible, and no status can be set.		      */
    250/* ------------------------------------------------------------------ */
    251char * decimal32ToEngString(const decimal32 *d32, char *string){
    252  decNumber dn;				/* work */
    253  decimal32ToNumber(d32, &dn);
    254  decNumberToEngString(&dn, string);
    255  return string;
    256  } /* decimal32ToEngString */
    257
    258char * decimal32ToString(const decimal32 *d32, char *string){
    259  uInt msd;			   /* coefficient MSD */
    260  Int  exp;			   /* exponent top two bits or full */
    261  uInt comb;			   /* combination field */
    262  char *cstart;			   /* coefficient start */
    263  char *c;			   /* output pointer in string */
    264  const uInt *pu;		   /* work */
    265  const uByte *u;		   /* .. */
    266  char *s, *t;			   /* .. (source, target) */
    267  Int  dpd;			   /* .. */
    268  Int  pre, e;			   /* .. */
    269  uInt sour;			   /* source 32-bit */
    270
    271  /* load source from storage; this is endian */
    272  pu=(const uInt *)d32->bytes;	   /* overlay */
    273  sour=*pu;			   /* directly load the int */
    274
    275  c=string;			   /* where result will go */
    276  if (((Int)sour)<0) *c++='-';	   /* handle sign */
    277
    278  comb=(sour>>26)&0x1f;		   /* combination field */
    279  msd=COMBMSD[comb];		   /* decode the combination field */
    280  exp=COMBEXP[comb];		   /* .. */
    281
    282  if (exp==3) {
    283    if (msd==0) {		   /* infinity */
    284      strcpy(c,	  "Inf");
    285      strcpy(c+3, "inity");
    286      return string;		   /* easy */
    287      }
    288    if (sour&0x02000000) *c++='s'; /* sNaN */
    289    strcpy(c, "NaN");		   /* complete word */
    290    c+=3;			   /* step past */
    291    if ((sour&0x000fffff)==0) return string; /* zero payload */
    292    /* otherwise drop through to add integer; set correct exp */
    293    exp=0; msd=0;		   /* setup for following code */
    294    }
    295   else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */
    296
    297  /* convert 7 digits of significand to characters */
    298  cstart=c;			   /* save start of coefficient */
    299  if (msd) *c++='0'+(char)msd;	   /* non-zero most significant digit */
    300
    301  /* Now decode the declets.  After extracting each one, it is */
    302  /* decoded to binary and then to a 4-char sequence by table lookup; */
    303  /* the 4-chars are a 1-char length (significant digits, except 000 */
    304  /* has length 0).  This allows us to left-align the first declet */
    305  /* with non-zero content, then remaining ones are full 3-char */
    306  /* length.  We use fixed-length memcpys because variable-length */
    307  /* causes a subroutine call in GCC.  (These are length 4 for speed */
    308  /* and are safe because the array has an extra terminator byte.) */
    309  #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4];			  \
    310		   if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}	  \
    311		    else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
    312
    313  dpd=(sour>>10)&0x3ff;		   /* declet 1 */
    314  dpd2char;
    315  dpd=(sour)&0x3ff;		   /* declet 2 */
    316  dpd2char;
    317
    318  if (c==cstart) *c++='0';	   /* all zeros -- make 0 */
    319
    320  if (exp==0) {			   /* integer or NaN case -- easy */
    321    *c='\0';			   /* terminate */
    322    return string;
    323    }
    324
    325  /* non-0 exponent */
    326  e=0;				   /* assume no E */
    327  pre=c-cstart+exp;
    328  /* [here, pre-exp is the digits count (==1 for zero)] */
    329  if (exp>0 || pre<-5) {	   /* need exponential form */
    330    e=pre-1;			   /* calculate E value */
    331    pre=1;			   /* assume one digit before '.' */
    332    } /* exponential form */
    333
    334  /* modify the coefficient, adding 0s, '.', and E+nn as needed */
    335  s=c-1;			   /* source (LSD) */
    336  if (pre>0) {			   /* ddd.ddd (plain), perhaps with E */
    337    char *dotat=cstart+pre;
    338    if (dotat<c) {		   /* if embedded dot needed... */
    339      t=c;				/* target */
    340      for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */
    341      *t='.';				/* insert the dot */
    342      c++;				/* length increased by one */
    343      }
    344
    345    /* finally add the E-part, if needed; it will never be 0, and has */
    346    /* a maximum length of 3 digits (E-101 case) */
    347    if (e!=0) {
    348      *c++='E';			   /* starts with E */
    349      *c++='+';			   /* assume positive */
    350      if (e<0) {
    351	*(c-1)='-';		   /* oops, need '-' */
    352	e=-e;			   /* uInt, please */
    353	}
    354      u=&BIN2CHAR[e*4];		   /* -> length byte */
    355      memcpy(c, u+4-*u, 4);	   /* copy fixed 4 characters [is safe] */
    356      c+=*u;			   /* bump pointer appropriately */
    357      }
    358    *c='\0';			   /* add terminator */
    359    /*printf("res %s\n", string); */
    360    return string;
    361    } /* pre>0 */
    362
    363  /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
    364  t=c+1-pre;
    365  *(t+1)='\0';				/* can add terminator now */
    366  for (; s>=cstart; s--, t--) *t=*s;	/* shift whole coefficient right */
    367  c=cstart;
    368  *c++='0';				/* always starts with 0. */
    369  *c++='.';
    370  for (; pre<0; pre++) *c++='0';	/* add any 0's after '.' */
    371  /*printf("res %s\n", string); */
    372  return string;
    373  } /* decimal32ToString */
    374
    375/* ------------------------------------------------------------------ */
    376/* to-number -- conversion from numeric string			      */
    377/*								      */
    378/*   decimal32FromString(result, string, set);			      */
    379/*								      */
    380/*  result  is the decimal32 format number which gets the result of   */
    381/*	    the conversion					      */
    382/*  *string is the character string which should contain a valid      */
    383/*	    number (which may be a special value)		      */
    384/*  set	    is the context					      */
    385/*								      */
    386/* The context is supplied to this routine is used for error handling */
    387/* (setting of status and traps) and for the rounding mode, only.     */
    388/* If an error occurs, the result will be a valid decimal32 NaN.      */
    389/* ------------------------------------------------------------------ */
    390decimal32 * decimal32FromString(decimal32 *result, const char *string,
    391				decContext *set) {
    392  decContext dc;			     /* work */
    393  decNumber dn;				     /* .. */
    394
    395  decContextDefault(&dc, DEC_INIT_DECIMAL32); /* no traps, please */
    396  dc.round=set->round;			      /* use supplied rounding */
    397
    398  decNumberFromString(&dn, string, &dc);     /* will round if needed */
    399  decimal32FromNumber(result, &dn, &dc);
    400  if (dc.status!=0) {			     /* something happened */
    401    decContextSetStatus(set, dc.status);     /* .. pass it on */
    402    }
    403  return result;
    404  } /* decimal32FromString */
    405
    406/* ------------------------------------------------------------------ */
    407/* decimal32IsCanonical -- test whether encoding is canonical	      */
    408/*   d32 is the source decimal32				      */
    409/*   returns 1 if the encoding of d32 is canonical, 0 otherwise	      */
    410/* No error is possible.					      */
    411/* ------------------------------------------------------------------ */
    412uint32_t decimal32IsCanonical(const decimal32 *d32) {
    413  decNumber dn;				/* work */
    414  decimal32 canon;			/* .. */
    415  decContext dc;			/* .. */
    416  decContextDefault(&dc, DEC_INIT_DECIMAL32);
    417  decimal32ToNumber(d32, &dn);
    418  decimal32FromNumber(&canon, &dn, &dc);/* canon will now be canonical */
    419  return memcmp(d32, &canon, DECIMAL32_Bytes)==0;
    420  } /* decimal32IsCanonical */
    421
    422/* ------------------------------------------------------------------ */
    423/* decimal32Canonical -- copy an encoding, ensuring it is canonical   */
    424/*   d32 is the source decimal32				      */
    425/*   result is the target (may be the same decimal32)		      */
    426/*   returns result						      */
    427/* No error is possible.					      */
    428/* ------------------------------------------------------------------ */
    429decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) {
    430  decNumber dn;				/* work */
    431  decContext dc;			/* .. */
    432  decContextDefault(&dc, DEC_INIT_DECIMAL32);
    433  decimal32ToNumber(d32, &dn);
    434  decimal32FromNumber(result, &dn, &dc);/* result will now be canonical */
    435  return result;
    436  } /* decimal32Canonical */
    437
    438#if DECTRACE || DECCHECK
    439/* Macros for accessing decimal32 fields.  These assume the argument
    440   is a reference (pointer) to the decimal32 structure, and the
    441   decimal32 is in network byte order (big-endian) */
    442/* Get sign */
    443#define decimal32Sign(d)       ((unsigned)(d)->bytes[0]>>7)
    444
    445/* Get combination field */
    446#define decimal32Comb(d)       (((d)->bytes[0] & 0x7c)>>2)
    447
    448/* Get exponent continuation [does not remove bias] */
    449#define decimal32ExpCon(d)     ((((d)->bytes[0] & 0x03)<<4)	      \
    450			     | ((unsigned)(d)->bytes[1]>>4))
    451
    452/* Set sign [this assumes sign previously 0] */
    453#define decimal32SetSign(d, b) {				      \
    454  (d)->bytes[0]|=((unsigned)(b)<<7);}
    455
    456/* Set exponent continuation [does not apply bias] */
    457/* This assumes range has been checked and exponent previously 0; */
    458/* type of exponent must be unsigned */
    459#define decimal32SetExpCon(d, e) {				      \
    460  (d)->bytes[0]|=(uint8_t)((e)>>4);				      \
    461  (d)->bytes[1]|=(uint8_t)(((e)&0x0F)<<4);}
    462
    463/* ------------------------------------------------------------------ */
    464/* decimal32Show -- display a decimal32 in hexadecimal [debug aid]    */
    465/*   d32 -- the number to show					      */
    466/* ------------------------------------------------------------------ */
    467/* Also shows sign/cob/expconfields extracted - valid bigendian only */
    468void decimal32Show(const decimal32 *d32) {
    469  char buf[DECIMAL32_Bytes*2+1];
    470  Int i, j=0;
    471
    472  if (DECLITEND) {
    473    for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
    474      sprintf(&buf[j], "%02x", d32->bytes[3-i]);
    475      }
    476    printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
    477	   d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f,
    478	   ((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4));
    479    }
    480   else {
    481    for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
    482      sprintf(&buf[j], "%02x", d32->bytes[i]);
    483      }
    484    printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
    485	   decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32));
    486    }
    487  } /* decimal32Show */
    488#endif