require_extension('D');
require_extension(EXT_ZFA);
require_fp;
uint64_t a = FRS1_D.v;

uint32_t sign = signF64UI(a);
uint32_t exp  = expF64UI(a);
uint64_t frac = fracF64UI(a);

bool inexact = false;
bool invalid = false;

if (exp == 0) {
  inexact = (frac != 0);
  frac = 0;
} else if (exp == 0x7ff) {
  /* inf or NaN */
  invalid = true;
  frac = 0;
} else {
  int true_exp = exp - 1023;
  int shift = true_exp - 52;

  /* Restore implicit bit.  */
  frac |= 1ull << 52;

  /* Shift the fraction into place.  */
  if (shift >= 64) {
    /* The fraction is shifted out entirely.  */
    frac = 0;
  } else  if ((shift >= 0) && (shift < 64)) {
    /* The number is so large we must shift the fraction left.  */
    frac <<= shift;
  } else if ((shift > -64) && (shift < 0)) {
    /* Normal case -- shift right and notice if bits shift out.  */
    inexact = (frac << (64 + shift)) != 0;
    frac >>= -shift;
  } else {
    /* The fraction is shifted out entirely.  */
    frac = 0;
    inexact = true;
  }

  /* Handle overflows */
  if (true_exp > 31 || frac > (sign ? 0x80000000ull : 0x7fffffff)) {
    /* Overflow, for which this operation raises invalid.  */
    invalid = true;
    inexact = false;  /* invalid takes precedence */
  }

  /* Honor the sign.  */
  if (sign) {
    frac = -frac;
  }
}

WRITE_RD(sext32(frac));
raise_fp_exceptions((inexact ? softfloat_flag_inexact : 0) |
		    (invalid ? softfloat_flag_invalid : 0));
