示例#1
0
文件: sankoff.c 项目: amnh/poy5
void
sankoff_canonize (elt_p ep, int * cm)
{
    int i; int j;
    int state; int newe; 
    int newbeta;
    int mincost=infinity,state_w_mincost=0;
    sankoff_get_min_state(ep,&mincost,&state_w_mincost);
    int num_states = ep->num_states;
    for (i=0;i<num_states;i++) {
        state = sankoff_get_state(ep,i);
        newe = (is_infinity(state)) ? infinity : state-mincost;
        sankoff_set_e(ep,i,newe);
    }
    int best; int thise;
    for (i=0;i<num_states;i++) {
        newbeta = infinity;
        for (j=num_states-1;j>=0;j--) {
           thise = sankoff_get_e(ep,j);
           best = (is_infinity(thise)) ? thise : thise + sankoff_return_value(cm,num_states,num_states,i,j);
           store_min(best,&newbeta);
        }
        sankoff_set_beta(ep,i,newbeta);
    }
    return;
}
示例#2
0
文件: sankoff.c 项目: amnh/poy5
__inline int
#elif __clang__
int
#else
inline int
#endif
cost_plus (int a, int b)
{
    if ((is_infinity(a))||(is_infinity(b))) return infinity;
    else return(a+b);
}
示例#3
0
文件: sankoff.c 项目: amnh/poy5
__inline int
#elif __clang__
int
#else
inline int
#endif
cost_less_or_equal (int a, int b)
{
    if (is_infinity(a)) return 0;
    else if (is_infinity(b)) return 1;
    else return (a<=b);
}
示例#4
0
void ieee_floatt::extract_base10(
  mp_integer &_fraction,
  mp_integer &_exponent) const
{
  if(is_zero() || is_NaN() || is_infinity())
  {
    _fraction=_exponent=0;
    return;
  }

  _exponent=exponent;
  _fraction=fraction;

  // adjust exponent
  _exponent-=spec.f;

  // now make it base 10
  if(_exponent>=0)
  {
    _fraction*=power(2, _exponent);
    _exponent=0;
  }
  else // _exponent<0
  {
    // 10/2=5 -- this makes it base 10
    _fraction*=power(5, -_exponent);
  }

  // try to re-normalize
  while((_fraction%10)==0)
  {
    _fraction/=10;
    ++_exponent;
  }
}
示例#5
0
 inline
 int_adapter operator-(const int_adapter<rhs_type>& rhs)const
 {
   if(is_special() || rhs.is_special())
   {
     if (is_nan() || rhs.is_nan()) 
     {
       return int_adapter::not_a_number();
     }
     if((is_pos_inf(value_) && rhs.is_pos_inf(rhs.as_number())) ||
        (is_neg_inf(value_) && rhs.is_neg_inf(rhs.as_number())) )
     {
       return int_adapter::not_a_number();
     }
     if (is_infinity()) 
     {
       return *this;
     }
     if (rhs.is_pos_inf(rhs.as_number())) 
     {
       return int_adapter::neg_infinity();
     }
     if (rhs.is_neg_inf(rhs.as_number())) 
     {
       return int_adapter::pos_infinity();
     }
   }
   return int_adapter<int_type>(value_ - rhs.as_number());
 }
示例#6
0
float_utilst::unbiased_floatt float_utilst::unpack(const bvt &src)
{
  assert(src.size()==spec.width());

  unbiased_floatt result;

  result.sign=sign_bit(src);

  result.fraction=get_fraction(src);
  result.fraction.push_back(is_normal(src)); // add hidden bit

  result.exponent=get_exponent(src);
  assert(result.exponent.size()==spec.e);

  // unbias the exponent
  literalt denormal=bv_utils.is_zero(result.exponent);

  result.exponent=
    bv_utils.select(denormal,
      bv_utils.build_constant(-spec.bias()+1, spec.e),
      sub_bias(result.exponent));

  result.infinity=is_infinity(src);
  result.zero=is_zero(src);
  result.NaN=is_NaN(src);

  return result;
}
示例#7
0
文件: reals.c 项目: Pachot/mlworks
static mlval to_string(mlval arg)
{
  char buffer[40];
  size_t length;
  mlval string;

  double x = GETREAL (FIELD (arg,0));
  int prec = CINT (FIELD (arg,1));

  if (isnan(x))
    strcpy (buffer,"nan");
  else 
    if (is_infinity (x))
      if (x > 0.0) 
	strcpy (buffer,"inf");
      else strcpy (buffer,"~inf");
    else
      {
	size_t i, plus = 0;
	int point = 0;
	    
	sprintf(buffer, "%.*G", prec, x);

	length = strlen(buffer);

	for(i=0; i<length; ++i)
	  {
	    char c = buffer[i];

	    if(c == '-')
	      buffer[i] = '~';
	    else if(c == '.' || c == 'E')
	      point = 1;
	    else if(c == '+')
	      plus = i;
	  }
  
	if(plus)
	  {
	    for(i=plus; i<length; ++i)
	      buffer[i] = buffer[i+1];
	    length--;
	    
	  }
	
	if(!point)
	  {
	    buffer[length++] = '.';
	    buffer[length++] = '0';
	    buffer[length] = '\0';
	  }
      }

  length = strlen (buffer);
  string = allocate_string(length+1);
  strcpy(CSTRING(string), buffer);

 return(string);
}
示例#8
0
文件: sankoff.c 项目: amnh/poy5
__inline int
#elif __clang__
int
#else
inline int
#endif
cost_minus (int a, int b)
{
    if (is_infinity(a)) {
        assert(!(is_infinity(b)));
        return INT_MAX;
    }
    else if (is_infinity(b)) {
        return 0;
    }
    else return(a-b);
}
示例#9
0
 int_adapter operator-(int_type rhs) const
 {
   if (is_nan()) {
     return int_adapter<int_type>(not_a_number());
   }
   if (is_infinity()) {
     return *this;
   }
   return int_adapter<int_type>(value_ - rhs);
 }
// Floating Negative Multiply-Sub
static void
fnmsub(ThreadState *state, Instruction instr)
{
   double a, b, c, d;
   a = state->fpr[instr.frA].paired0;
   b = state->fpr[instr.frB].paired0;
   c = state->fpr[instr.frC].paired0;

   state->fpscr.vximz = is_infinity(a * c) && is_zero(c);
   state->fpscr.vxisi = is_infinity(a * c) || is_infinity(c);
   state->fpscr.vxsnan = is_signalling_nan(a) || is_signalling_nan(b) || is_signalling_nan(c);

   d = -((a * c) - b);
   updateFPSCR(state);
   updateFPRF(state, d);
   state->fpr[instr.frD].paired0 = d;

   if (instr.rc) {
      updateFloatConditionRegister(state);
   }
}
static void
fsubGeneric(ThreadState *state, Instruction instr)
{
   double a, b, d;
   a = state->fpr[instr.frA].paired0;
   b = state->fpr[instr.frB].paired0;

   state->fpscr.vxisi = is_infinity(a) && is_infinity(b);
   state->fpscr.vxsnan = is_signalling_nan(a) || is_signalling_nan(b);

   d = static_cast<Type>(a - b);
   updateFPSCR(state);

   d = checkNan<Type>(d, a, b);
   updateFPRF(state, d);
   state->fpr[instr.frD].paired0 = d;

   if (instr.rc) {
      updateFloatConditionRegister(state);
   }
}
示例#12
0
 int_adapter operator-(const int_adapter& rhs) const
 {
   if (is_nan() || rhs.is_nan()) {
     return int_adapter<int_type>(not_a_number());
   }
   if (is_infinity()) {
     return *this;
   }
   if (rhs.is_infinity()) {
     return rhs;
   }
   return int_adapter<int_type>(value_ - rhs.value_);
 }
示例#13
0
 int_adapter operator+(const int_type rhs) const
 {
   if(is_special())
   {
     if (is_nan()) 
     {
       return int_adapter<int_type>(not_a_number());
     }
     if (is_infinity()) 
     {
       return *this;
     }
   }
   return int_adapter<int_type>(value_ + rhs);
 }
示例#14
0
文件: sankoff.c 项目: amnh/poy5
void 
sankoff_print_int_array (char * str, int * arr, int size)
{
    printf("%s,",str);
    int i, tmp;
    for (i=0;i<size;i++)
    {
        tmp = arr[i];
        if(is_infinity(tmp)) printf ("inf,");
        else
        printf("%d,",tmp);
    }
    printf("\n");
    fflush(stdout);
}
示例#15
0
 // should templatize this to be consistant with op +-
 int_adapter operator%(const int_adapter& rhs)const
 {
   if(this->is_special() || rhs.is_special())
   {
     if(is_infinity() && rhs.is_infinity())
     {
       return int_adapter<int_type>(not_a_number());
     }
     if(rhs != 0)
     {
       return mult_div_specials(rhs);
     }
     else { // let divide by zero blow itself up
       return int_adapter<int_type>(value_ % rhs.value_);
     }
   }
   return int_adapter<int_type>(value_ % rhs.value_);
 }
示例#16
0
/// Sets *this to the next representable number closer to plus infinity (greater
/// = true) or minus infinity (greater = false).
void ieee_floatt::next_representable(bool greater)
{
  if(is_NaN())
    return;

  bool old_sign=get_sign();

  if(is_zero())
  {
    unpack(1);
    set_sign(!greater);

    return;
  }

  if(is_infinity())
  {
    if(get_sign()==greater)
    {
      make_fltmax();
      set_sign(old_sign);
    }
    return;
  }

  bool dir;
  if(greater)
    dir=!get_sign();
  else
    dir=get_sign();

  set_sign(false);

  mp_integer old=pack();
  if(dir)
    ++old;
  else
    --old;

  unpack(old);

  // sign change impossible (zero case caught earler)
  set_sign(old_sign);
}
// Floating Multiply-Add Single
static void
fmadds(ThreadState *state, Instruction instr)
{
   double a, b, c, d;
   a = state->fpr[instr.frA].paired0;
   b = state->fpr[instr.frB].paired0;
   c = state->fpr[instr.frC].paired0;

   state->fpscr.vxsnan = is_signalling_nan(a) || is_signalling_nan(b) || is_signalling_nan(c);
   state->fpscr.vxisi = is_infinity(a * c) || is_infinity(c);
   state->fpscr.vximz = is_infinity(a * c) && is_zero(c);

   d = a * c;
   if (is_nan(d)) {
      if (is_nan(a)) {
         d = make_quiet(a);
      } else if (is_nan(b)) {
         d = make_quiet(b);
      } else if (is_nan(c)) {
         d = make_quiet(c);
      } else {
         d = make_nan<double>();
      }
   } else {
      if (is_infinity(d) && is_infinity(b) && !(is_infinity(a) || is_infinity(c))) {
         d = b;
      } else {
         d = d + b;
         if (is_nan(d)) {
            if (is_nan(b)) {
               d = make_quiet(b);
            } else {
               d = make_nan<double>();
            }
         }
      }
   }

   updateFPSCR(state);
   updateFPRF(state, d);
   state->fpr[instr.frD].paired0 = static_cast<float>(d);

   if (instr.rc) {
      updateFloatConditionRegister(state);
   }
}
static void
fmulGeneric(ThreadState *state, Instruction instr)
{
   double a, c, d;
   a = state->fpr[instr.frA].paired0;
   c = state->fpr[instr.frC].paired0;

   state->fpscr.vximz = is_infinity(a) && is_zero(c);
   state->fpscr.vxsnan = is_signalling_nan(a) || is_signalling_nan(c);

   d = static_cast<Type>(a * c);
   updateFPSCR(state);

   d = checkNan<Type>(d, a, c);
   updateFPRF(state, d);
   state->fpr[instr.frD].paired0 = d;

   if (instr.rc) {
      updateFloatConditionRegister(state);
   }
}
示例#19
0
 inline S
 generalized_mean(I first, I last, T p) {
   // Check for well known cases.
   if (p == -1)
     return harmonic_mean(first, last);
   if (p == 0)
     return geometric_mean(first, last);
   if (p == 1)
     return arithmetic_mean(first, last);
   if (p == 2)
     return quadratic_mean(first, last);
   if (p == 3)
     return cubic_mean(first, last);
   
   // Either handle the infinity case or compute the generalized
   // value.
   if (is_infinity(p))
     return generalized_mean_inf(first, last, p);
   else
     return generalized_mean_non_inf(first, last, p);
 }
示例#20
0
void ieee_floatt::extract_base2(
  mp_integer &_fraction,
  mp_integer &_exponent) const
{
  if(is_zero() || is_NaN() || is_infinity())
  {
    _fraction=_exponent=0;
    return;
  }

  _exponent=exponent;
  _fraction=fraction;

  // adjust exponent
  _exponent-=spec.f;

  // try to integer-ize
  while((_fraction%2)==0)
  {
    _fraction/=2;
    ++_exponent;
  }
}
示例#21
0
int runTests(const std::string &path)
{
   uint32_t testsFailed = 0, testsPassed = 0;
   auto baseAddress = cpu::VirtualAddress { 0x02000000u };
   auto basePhysicalAddress = cpu::PhysicalAddress { 0x50000000u };
   auto codeSize = 2048u;

   cpu::allocateVirtualAddress(baseAddress, codeSize);
   cpu::mapMemory(baseAddress, basePhysicalAddress, codeSize, cpu::MapPermission::ReadWrite);

   Instruction bclr = encodeInstruction(InstructionID::bclr);
   bclr.bo = 0x1f;
   mem::write(baseAddress.getAddress() + 4, bclr.value);

   auto ec = std::error_code { };
   for (auto itr = std::filesystem::directory_iterator { "/tests", ec }; itr != end(itr); ++itr) {
      std::ifstream file(itr->path().string(), std::ifstream::in | std::ifstream::binary);
      cereal::BinaryInputArchive cerealInput(file);
      TestFile testFile;

      // Parse test file with cereal
      testFile.name = itr->path().filename().string();
      cerealInput(testFile);

      // Run tests
      for (auto &test : testFile.tests) {
         bool failed = false;

         if (!TEST_FMADDSUB) {
            auto data = espresso::decodeInstruction(test.instr);
            switch (data->id) {
            case InstructionID::fmadd:
            case InstructionID::fmadds:
            case InstructionID::fmsub:
            case InstructionID::fmsubs:
            case InstructionID::fnmadd:
            case InstructionID::fnmadds:
            case InstructionID::fnmsub:
            case InstructionID::fnmsubs:
               failed = true;
               break;
            }
            if (failed) {
               continue;
            }
         }

         // Setup core state from test input
         cpu::CoreRegs *state = cpu::this_core::state();
         memset(state, 0, sizeof(cpu::CoreRegs));
         state->cia = 0;
         state->nia = baseAddress.getAddress();
         state->xer = test.input.xer;
         state->cr = test.input.cr;
         state->fpscr = test.input.fpscr;
         state->ctr = test.input.ctr;

         for (auto i = 0; i < 4; ++i) {
            state->gpr[i + 3] = test.input.gpr[i];
            state->fpr[i + 1].paired0 = test.input.fr[i];
         }

         // Execute test
         mem::write(baseAddress.getAddress(), test.instr.value);
         cpu::clearInstructionCache();
         cpu::this_core::executeSub();

         // Check XER (all bits)
         if (state->xer.value != test.output.xer.value) {
            gLog->error("Test failed, xer expected {:08X} found {:08X}", test.output.xer.value, state->xer.value);
            failed = true;
         }

         // Check Condition Register (all bits)
         if (state->cr.value != test.output.cr.value) {
            gLog->error("Test failed, cr expected {:08X} found {:08X}", test.output.cr.value, state->cr.value);
            failed = true;
         }

         // Check FPSCR
         if (TEST_FPSCR) {
            if (!TEST_FPSCR_FR) {
               state->fpscr.fr = 0;
               test.output.fpscr.fr = 0;
            }

            if (!TEST_FPSCR_UX) {
               state->fpscr.ux = 0;
               test.output.fpscr.ux = 0;
            }

            auto state_fpscr = state->fpscr.value;
            auto test_fpscr = test.output.fpscr.value;

            if (state_fpscr != test_fpscr) {
               gLog->error("Test failed, fpscr {:08X} found {:08X}", test.output.fpscr.value, state->fpscr.value);
               compareFPSCR(test.input.fpscr, state->fpscr, test.output.fpscr);
               failed = true;
            }
         }

         // Check CTR
         if (state->ctr != test.output.ctr) {
            gLog->error("Test failed, ctr expected {:08X} found {:08X}", test.output.ctr, state->ctr);
            failed = true;
         }

         // Check all GPR
         for (auto i = 0; i < 4; ++i) {
            auto reg = i + hwtest::GPR_BASE;
            auto value = state->gpr[reg];
            auto expected = test.output.gpr[i];

            if (value != expected) {
               gLog->error("Test failed, r{} expected {:08X} found {:08X}", reg, expected, value);
               failed = true;
            }
         }

         // Check all FPR
         for (auto i = 0; i < 4; ++i) {
            auto reg = i + hwtest::FPR_BASE;
            auto value = state->fpr[reg].value;
            auto expected = test.output.fr[i];

            if (!is_nan(value) && !is_nan(expected) && !is_infinity(value) && !is_infinity(expected)) {
               double dval = value / expected;

               if (dval < 0.999 || dval > 1.001) {
                  gLog->error("Test failed, f{} expected {:16f} found {:16f}", reg, expected, value);
                  failed = true;
               }
            } else {
               if (is_nan(value) && is_nan(expected)) {
                  auto bits = get_float_bits(value);
                  bits.sign = get_float_bits(expected).sign;
                  value = bits.v;
               }

               if (bit_cast<uint64_t>(value) != bit_cast<uint64_t>(expected)) {
                  gLog->error("Test failed, f{} expected {:16X} found {:16X}", reg, bit_cast<uint64_t>(expected), bit_cast<uint64_t>(value));
                  failed = true;
               }
            }
         }

         if (failed) {
            Disassembly dis;

            // Print disassembly
            disassemble(test.instr, dis, baseAddress.getAddress());
            gLog->debug(dis.text);

            // Print all test fields
            gLog->debug("{:08x}            Input         Hardware           Interp", test.instr.value);

            for (auto field : dis.instruction->read) {
               printTestField(field, test.instr, &test.input, &test.output, state);
            }

            for (auto field : dis.instruction->write) {
               printTestField(field, test.instr, &test.input, &test.output, state);
            }

            for (auto field : dis.instruction->flags) {
               printTestField(field, test.instr, &test.input, &test.output, state);
            }

            gLog->debug("");
            ++testsFailed;
         } else {
            ++testsPassed;
         }
      }
   }

   if (testsFailed) {
      gLog->error("Failed {} of {} tests.", testsFailed, testsFailed + testsPassed);
   }

   return testsFailed;
}
示例#22
0
void ieee_floatt::next_representable(bool greater)
{
  if(is_NaN())
    return;
  
  bool old_sign = get_sign();

  if(is_zero())
  {
    unpack(1);
    set_sign(!greater);

    return;
  }

  if(is_infinity())
  {
    if(get_sign() == greater)
    {
      make_fltmax();
      set_sign(old_sign);
    } 
    return;
  }
  
  bool dir;
  if(greater)
  {
    if(get_sign())
      dir = false;
    else
      dir = true;
  } 
  else
  {
    if(get_sign())
      dir = true;
    else
      dir = false;
  }

  set_sign(false);

  mp_integer old = pack();
  if(dir)
    ++old;
  else
    --old;

  unpack(old);

  //sign change impossible (zero case caught earler)
  set_sign(old_sign);

  //mp_integer new_exp = exponent;
  //mp_integer new_frac = fraction + dir;

  //std::cout << exponent << ":" << fraction << std::endl;
  //std::cout << new_exp << ":" << new_frac << std::endl;
  
  //if(get_sign())
  //  new_frac.negate();

  //new_exp -= spec.f;
  //build(new_frac, new_exp);
}
示例#23
0
 //! check to see if time is a special value
 bool is_special() const
 {
   return(is_not_a_date_time() || is_infinity());
 }
示例#24
0
文件: reals.c 项目: Pachot/mlworks
static mlval fmt (mlval arg)
{
  char buffer[40];
  size_t length;
  mlval string;
  mlval format = FIELD (arg, 0);
  double x = GETREAL (FIELD (arg,1));
  int prec = 0;
  /* Check the precision first */
  if (format != EXACT_FORMAT) {
    int format_type = CINT (FIELD (format, 0));
    int min_prec = 0;

    /* Minimum precision is 0 for SCI and FIX, 1 for GEN. */
    if (format_type == GEN_FORMAT) 
      min_prec = 1;

    if (FIELD (format,1) == MLINT (0)) {
      /* Argument is NONE => Default precision. */
      prec = -1;
    } else {
      prec = CINT (FIELD (FIELD (format,1),1));
      if (prec < min_prec)
        exn_raise(perv_exn_ref_size);
    }
  }

  if (isnan (x))
    strcpy (buffer,"nan");
  else
    if (is_infinity (x))
      if (x > 0.0) 
	strcpy (buffer,"+inf");
      else strcpy (buffer,"-inf");
    else
      if (format == EXACT_FORMAT) { /* EXACT conversion required */
	/* Note that this doesn't do the right thing with NaN's, but */
	/* this should be taken care of on the ML side of things */
	int dec;
	int sign;
	char * ptr = buffer;
	char * digits = dtoa (x,0,100,&dec,&sign,NULL);
	char * dptr = digits;
	if (sign)
	  *ptr++ = '~';
	*ptr++ = '0';
	*ptr++ = '.';
	/* Don't copy null byte here */
	while (*dptr)
	  *ptr++=*dptr++;
	if (dec != 0){
	  *ptr++ = 'E';
	  if (dec < 0) {
	    dec = -dec;
	    *ptr++ = '~';
	  }
	  /* Now add the exponent */
	  sprintf (ptr,"%d",dec);
	  ptr += strlen (ptr);
	}
	*ptr++ = '\000';
	freedtoa (digits);
      } else {
	/* Now we have to decipher the format */
	size_t i, plus = 0;
	int point = 0;
	int format_type = CINT (FIELD (format,0));

	if (format_type == FIX_FORMAT) /* FIX */
	  sprintf (buffer, "%.*f", prec < 0 ? 6 : prec, x);
	else if (format_type == GEN_FORMAT) /* GEN */
	  sprintf (buffer, "%.*G", prec < 0 ? 12 : prec,x);
	else if (format_type == SCI_FORMAT) /* SCI */
	  sprintf (buffer, "%.*E", prec < 0 ? 6 : prec, x);
	else sprintf(buffer, "%.18G", x);

	length = strlen(buffer);

	/* Now check for correct printing of negative zeroes */
	if (x == 0.0) {
	  switch (check_neg_zero(&x)) {
	  case 2: /* -0.0 */
	    /* May need to modify the output here */
	    if (*buffer != '-') {
	      /* Yes, we do need to modify */
	      if (*buffer == '+') {
		*buffer = '-';
	      } else {
		for (i = length+1; i > 0; i--) {
		  buffer[i] = buffer[i-1]; /* Move the characters along the buffer */
		};
		length++;
		*buffer = '-';
	      }
	    }
	  case 0: /* Not actually 0.0 at all */
	  case 1: /* +0.0 */
	  default: /* This shouldn't happen */
	    /* No action required here */
	    break;
	  }
	}

	for(i=0; i<length; ++i) {
	  char c = buffer[i];

	  if(c == '-')
	    buffer[i] = '~';
	  else if(c == '.' || c == 'E')
	    point = i;
	  else if(c == '+')
	    plus = i;
	}

	/* Win32 screws up G format by printing too many digits */
	/* in the exponent. So we contract that part if necessary */

	if (point && buffer[point] == 'E') {
	  char c = buffer[point+1];
	  if (c == '+' || c == '~') point++;
	  if (buffer[point+1] == '0' &&
	      isdigit(buffer[point+2]) &&
	      isdigit(buffer[point+3])) {
	    buffer[point+1] = buffer[point+2];
	    buffer[point+2] = buffer[point+3];
	    buffer[point+3] = '\0';
	  }
	}

	if(plus) {
	  for(i=plus; i<length; ++i)
	    buffer[i] = buffer[i+1];
	  length--;
	}
	
	if(!point && (format_type != GEN_FORMAT)
                  && !(format_type == FIX_FORMAT && prec == 0)) {
	  buffer[length++] = '.';
	  buffer[length++] = '0';
	  buffer[length] = '\0';
	}
      }

  length = strlen (buffer);
  string = allocate_string(length+1);
  strcpy(CSTRING(string), buffer);

  return(string);
}
static bool
fmaSingle(cpu::Core *state, Instruction instr, float *result)
{
   double a, b, c;
   if (slotAB == 0) {
      a = state->fpr[instr.frA].paired0;
      b = state->fpr[instr.frB].paired0;
   } else {
      a = state->fpr[instr.frA].paired1;
      b = state->fpr[instr.frB].paired1;
   }
   if (slotC == 0) {
      c = state->fpr[instr.frC].paired0;
   } else {
      c = state->fpr[instr.frC].paired1;
   }
   const double addend = (flags & FMASubtract) ? -b : b;

   const bool vxsnan = is_signalling_nan(a) || is_signalling_nan(b) || is_signalling_nan(c);
   const bool vximz = (is_infinity(a) && is_zero(c)) || (is_zero(a) && is_infinity(c));
   const bool vxisi = (!vximz && !is_nan(a) && !is_nan(c)
                       && (is_infinity(a) || is_infinity(c)) && is_infinity(b)
                       && (std::signbit(a) ^ std::signbit(c)) != std::signbit(addend));

   state->fpscr.vxsnan |= vxsnan;
   state->fpscr.vxisi |= vxisi;
   state->fpscr.vximz |= vximz;

   if ((vxsnan || vxisi || vximz) && state->fpscr.ve) {
      return false;
   }

   float d;
   if (is_nan(a)) {
      d = make_quiet(truncate_double(a));
   } else if (is_nan(b)) {
      d = make_quiet(truncate_double(b));
   } else if (is_nan(c)) {
      d = make_quiet(truncate_double(c));
   } else if (vxisi || vximz) {
      d = make_nan<float>();
   } else {
      if (slotC == 0) {
         roundForMultiply(&a, &c);  // Not necessary for slot 1.
      }

      double d64 = std::fma(a, c, addend);
      if (state->fpscr.rn == espresso::FloatingPointRoundMode::Nearest) {
         d = roundFMAResultToSingle(d64, a, addend, c);
      } else {
         d = static_cast<float>(d64);
      }

      if (possibleUnderflow<float>(d)) {
         const int oldRound = fegetround();
         fesetround(FE_TOWARDZERO);

         volatile double addendTemp = addend;
         volatile float dummy;
         dummy = (float)std::fma(a, c, addendTemp);

         fesetround(oldRound);
      }

      if (flags & FMANegate) {
         d = -d;
      }
   }

   *result = d;
   return true;
}
static bool
psArithSingle(cpu::Core *state, Instruction instr, float *result)
{
   double a, b;
   if (slotA == 0) {
      a = state->fpr[instr.frA].paired0;
   } else {
      a = state->fpr[instr.frA].paired1;
   }
   if (slotB == 0) {
      b = state->fpr[op == PSMul ? instr.frC : instr.frB].paired0;
   } else {
      b = state->fpr[op == PSMul ? instr.frC : instr.frB].paired1;
   }

   const bool vxsnan = is_signalling_nan(a) || is_signalling_nan(b);
   bool vxisi, vximz, vxidi, vxzdz, zx;
   switch (op) {
   case PSAdd:
      vxisi = is_infinity(a) && is_infinity(b) && std::signbit(a) != std::signbit(b);
      vximz = false;
      vxidi = false;
      vxzdz = false;
      zx = false;
      break;
   case PSSub:
      vxisi = is_infinity(a) && is_infinity(b) && std::signbit(a) == std::signbit(b);
      vximz = false;
      vxidi = false;
      vxzdz = false;
      zx = false;
      break;
   case PSMul:
      vxisi = false;
      vximz = (is_infinity(a) && is_zero(b)) || (is_zero(a) && is_infinity(b));
      vxidi = false;
      vxzdz = false;
      zx = false;
      break;
   case PSDiv:
      vxisi = false;
      vximz = false;
      vxidi = is_infinity(a) && is_infinity(b);
      vxzdz = is_zero(a) && is_zero(b);
      zx = !(vxzdz || vxsnan) && is_zero(b);
      break;
   }

   state->fpscr.vxsnan |= vxsnan;
   state->fpscr.vxisi |= vxisi;
   state->fpscr.vximz |= vximz;
   state->fpscr.vxidi |= vxidi;
   state->fpscr.vxzdz |= vxzdz;
   state->fpscr.zx |= zx;

   const bool vxEnabled = (vxsnan || vxisi || vximz || vxidi || vxzdz) && state->fpscr.ve;
   const bool zxEnabled = zx && state->fpscr.ze;
   if (vxEnabled || zxEnabled) {
      return false;
   }

   float d;
   if (is_nan(a)) {
      d = make_quiet(truncate_double(a));
   } else if (is_nan(b)) {
      d = make_quiet(truncate_double(b));
   } else if (vxisi || vximz || vxidi || vxzdz) {
      d = make_nan<float>();
   } else {
      switch (op) {
      case PSAdd:
         d = static_cast<float>(a + b);
         break;
      case PSSub:
         d = static_cast<float>(a - b);
         break;
      case PSMul:
         if (slotB == 0) {
            roundForMultiply(&a, &b);  // Not necessary for slot 1.
         }
         d = static_cast<float>(a * b);
         break;
      case PSDiv:
         d = static_cast<float>(a / b);
         break;
      }

      if (possibleUnderflow<float>(d)) {
         const int oldRound = fegetround();
         fesetround(FE_TOWARDZERO);

         volatile double bTemp = b;
         volatile float dummy;
         switch (op) {
         case PSAdd:
            dummy = static_cast<float>(a + bTemp);
            break;
         case PSSub:
            dummy = static_cast<float>(a - bTemp);
            break;
         case PSMul:
            dummy = static_cast<float>(a * bTemp);
            break;
         case PSDiv:
            dummy = static_cast<float>(a / bTemp);
            break;
         }
         fesetround(oldRound);
      }
   }

   *result = d;
   return true;
}
示例#27
0
 bool is_special() const
 {
   return(is_infinity() || is_nan()); 
 }
示例#28
0
bool runTests(const std::string &path)
{
   uint32_t testsFailed = 0, testsPassed = 0;
   uint32_t baseAddress = mem::MEM2Base;

   Instruction bclr = encodeInstruction(InstructionID::bclr);
   bclr.bo = 0x1f;
   mem::write(baseAddress + 4, bclr.value);

   fs::FileSystem filesystem;
   fs::FolderEntry entry;
   fs::HostPath base = path;
   filesystem.mountHostFolder("/tests", base, fs::Permissions::Read);
   auto folder = filesystem.openFolder("/tests");

   while (folder->read(entry)) {
      std::ifstream file(base.join(entry.name).path(), std::ifstream::in | std::ifstream::binary);
      cereal::BinaryInputArchive cerealInput(file);
      TestFile testFile;

      // Parse test file with cereal
      testFile.name = entry.name;
      cerealInput(testFile);

      // Run tests
      gLog->info("Checking {}", testFile.name);

      for (auto &test : testFile.tests) {
         bool failed = false;

         if (!TEST_FMADDSUB) {
            auto data = espresso::decodeInstruction(test.instr);
            switch (data->id) {
            case InstructionID::fmadd:
            case InstructionID::fmadds:
            case InstructionID::fmsub:
            case InstructionID::fmsubs:
            case InstructionID::fnmadd:
            case InstructionID::fnmadds:
            case InstructionID::fnmsub:
            case InstructionID::fnmsubs:
               failed = true;
               break;
            }
            if (failed) {
               continue;
            }
         }

         // Setup core state from test input
         cpu::CoreRegs *state = cpu::this_core::state();
         memset(state, 0, sizeof(cpu::CoreRegs));
         state->cia = 0;
         state->nia = baseAddress;
         state->xer = test.input.xer;
         state->cr = test.input.cr;
         state->fpscr = test.input.fpscr;
         state->ctr = test.input.ctr;

         for (auto i = 0; i < 4; ++i) {
            state->gpr[i + 3] = test.input.gpr[i];
            state->fpr[i + 1].paired0 = test.input.fr[i];
         }

         // Execute test
         mem::write(baseAddress, test.instr.value);
         cpu::jit::clearCache();
         cpu::this_core::executeSub();

         // Check XER (all bits)
         if (state->xer.value != test.output.xer.value) {
            gLog->error("Test failed, xer expected {:08X} found {:08X}", test.output.xer.value, state->xer.value);
            failed = true;
         }

         // Check Condition Register (all bits)
         if (state->cr.value != test.output.cr.value) {
            gLog->error("Test failed, cr expected {:08X} found {:08X}", test.output.cr.value, state->cr.value);
            failed = true;
         }

         // Check FPSCR
         if (TEST_FPSCR) {
            if (!TEST_FPSCR_FR) {
               state->fpscr.fr = 0;
               test.output.fpscr.fr = 0;
            }

            if (!TEST_FPSCR_UX) {
               state->fpscr.ux = 0;
               test.output.fpscr.ux = 0;
            }

            auto state_fpscr = state->fpscr.value;
            auto test_fpscr = test.output.fpscr.value;

            if (state_fpscr != test_fpscr) {
               gLog->error("Test failed, fpscr {:08X} found {:08X}", test.output.fpscr.value, state->fpscr.value);
               compareFPSCR(test.input.fpscr, state->fpscr, test.output.fpscr);
               failed = true;
            }
         }

         // Check CTR
         if (state->ctr != test.output.ctr) {
            gLog->error("Test failed, ctr expected {:08X} found {:08X}", test.output.ctr, state->ctr);
            failed = true;
         }

         // Check all GPR
         for (auto i = 0; i < 4; ++i) {
            auto reg = i + hwtest::GPR_BASE;
            auto value = state->gpr[reg];
            auto expected = test.output.gpr[i];

            if (value != expected) {
               gLog->error("Test failed, r{} expected {:08X} found {:08X}", reg, expected, value);
               failed = true;
            }
         }

         // Check all FPR
         for (auto i = 0; i < 4; ++i) {
            auto reg = i + hwtest::FPR_BASE;
            auto value = state->fpr[reg].value;
            auto expected = test.output.fr[i];

            if (!is_nan(value) && !is_nan(expected) && !is_infinity(value) && !is_infinity(expected)) {
               double dval = value / expected;

               if (dval < 0.999 || dval > 1.001) {
                  gLog->error("Test failed, f{} expected {:16f} found {:16f}", reg, expected, value);
                  failed = true;
               }
            } else {
               if (is_nan(value) && is_nan(expected)) {
                  auto bits = get_float_bits(value);
                  bits.sign = get_float_bits(expected).sign;
                  value = bits.v;
               }

               if (bit_cast<uint64_t>(value) != bit_cast<uint64_t>(expected)) {
                  gLog->error("Test failed, f{} expected {:16X} found {:16X}", reg, bit_cast<uint64_t>(expected), bit_cast<uint64_t>(value));
                  failed = true;
               }
            }
         }

         if (failed) {
            Disassembly dis;

            // Print disassembly
            disassemble(test.instr, dis, baseAddress);
            gLog->debug(dis.text);

            // Print all test fields
            gLog->debug("{:08x}            Input         Hardware           Interp", test.instr.value);

            for (auto field : dis.instruction->read) {
               printTestField(field, test.instr, &test.input, &test.output, state);
            }

            for (auto field : dis.instruction->write) {
               printTestField(field, test.instr, &test.input, &test.output, state);
            }

            for (auto field : dis.instruction->flags) {
               printTestField(field, test.instr, &test.input, &test.output, state);
            }

            gLog->debug("");
            ++testsFailed;
         } else {
            ++testsPassed;
         }
      }
   }

   gLog->info("Passed: {}, Failed: {}", testsPassed, testsFailed);
   return true;
}