예제 #1
0
파일: single_cpdo.c 프로젝트: 274914765/C
unsigned int SingleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
{
    FPA11 *fpa11 = GET_FPA11();
    float32 rFm;
    unsigned int Fm, opc_mask_shift;

    Fm = getFm(opcode);
    if (CONSTANT_FM(opcode)) {
        rFm = getSingleConstant(Fm);
    } else if (fpa11->fType[Fm] == typeSingle) {
        rFm = fpa11->fpreg[Fm].fSingle;
    } else {
        return 0;
    }

    opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
    if (!MONADIC_INSTRUCTION(opcode)) {
        unsigned int Fn = getFn(opcode);
        float32 rFn;

        if (fpa11->fType[Fn] == typeSingle &&
            dyadic_single[opc_mask_shift]) {
            rFn = fpa11->fpreg[Fn].fSingle;
            rFd->fSingle = dyadic_single[opc_mask_shift](roundData, rFn, rFm);
        } else {
            return 0;
        }
    } else {
        if (monadic_single[opc_mask_shift]) {
            rFd->fSingle = monadic_single[opc_mask_shift](roundData, rFm);
        } else {
            return 0;
        }
    }

    return 1;
}
예제 #2
0
파일: fpa11_cprt.c 프로젝트: 274914765/C
/* This instruction sets the flags N, Z, C, V in the FPSR. */
static unsigned int PerformComparison(const unsigned int opcode)
{
    FPA11 *fpa11 = GET_FPA11();
    unsigned int Fn = getFn(opcode), Fm = getFm(opcode);
    int e_flag = opcode & 0x400000;    /* 1 if CxFE */
    int n_flag = opcode & 0x200000;    /* 1 if CNxx */
    unsigned int flags = 0;

#ifdef CONFIG_FPE_NWFPE_XP
    floatx80 rFn, rFm;

    /* Check for unordered condition and convert all operands to 80-bit
       format.
       ?? Might be some mileage in avoiding this conversion if possible.
       Eg, if both operands are 32-bit, detect this and do a 32-bit
       comparison (cheaper than an 80-bit one).  */
    switch (fpa11->fType[Fn]) {
    case typeSingle:
        //printk("single.\n");
        if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
            goto unordered;
        rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
        break;

    case typeDouble:
        //printk("double.\n");
        if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
            goto unordered;
        rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
        break;

    case typeExtended:
        //printk("extended.\n");
        if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
            goto unordered;
        rFn = fpa11->fpreg[Fn].fExtended;
        break;

    default:
        return 0;
    }

    if (CONSTANT_FM(opcode)) {
        //printk("Fm is a constant: #%d.\n",Fm);
        rFm = getExtendedConstant(Fm);
        if (floatx80_is_nan(rFm))
            goto unordered;
    } else {
        //printk("Fm = r%d which contains a ",Fm);
        switch (fpa11->fType[Fm]) {
        case typeSingle:
            //printk("single.\n");
            if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
                goto unordered;
            rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
            break;

        case typeDouble:
            //printk("double.\n");
            if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
                goto unordered;
            rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
            break;

        case typeExtended:
            //printk("extended.\n");
            if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
                goto unordered;
            rFm = fpa11->fpreg[Fm].fExtended;
            break;

        default:
            return 0;
        }
    }

    if (n_flag)
        rFm.high ^= 0x8000;

    /* test for less than condition */
    if (floatx80_lt(rFn, rFm))
        flags |= CC_NEGATIVE;

    /* test for equal condition */
    if (floatx80_eq(rFn, rFm))
        flags |= CC_ZERO;

    /* test for greater than or equal condition */
    if (floatx80_lt(rFm, rFn))
        flags |= CC_CARRY;

#else
    if (CONSTANT_FM(opcode)) {
        /* Fm is a constant.  Do the comparison in whatever precision
           Fn happens to be stored in.  */
        if (fpa11->fType[Fn] == typeSingle) {
            float32 rFm = getSingleConstant(Fm);
            float32 rFn = fpa11->fpreg[Fn].fSingle;

            if (float32_is_nan(rFn))
                goto unordered;

            if (n_flag)
                rFm ^= 0x80000000;

            /* test for less than condition */
            if (float32_lt_nocheck(rFn, rFm))
                flags |= CC_NEGATIVE;

            /* test for equal condition */
            if (float32_eq_nocheck(rFn, rFm))
                flags |= CC_ZERO;

            /* test for greater than or equal condition */
            if (float32_lt_nocheck(rFm, rFn))
                flags |= CC_CARRY;
        } else {
            float64 rFm = getDoubleConstant(Fm);
            float64 rFn = fpa11->fpreg[Fn].fDouble;

            if (float64_is_nan(rFn))
                goto unordered;

            if (n_flag)
                rFm ^= 0x8000000000000000ULL;

            /* test for less than condition */
            if (float64_lt_nocheck(rFn, rFm))
                flags |= CC_NEGATIVE;

            /* test for equal condition */
            if (float64_eq_nocheck(rFn, rFm))
                flags |= CC_ZERO;

            /* test for greater than or equal condition */
            if (float64_lt_nocheck(rFm, rFn))
                flags |= CC_CARRY;
        }
    } else {
        /* Both operands are in registers.  */
        if (fpa11->fType[Fn] == typeSingle
            && fpa11->fType[Fm] == typeSingle) {
            float32 rFm = fpa11->fpreg[Fm].fSingle;
            float32 rFn = fpa11->fpreg[Fn].fSingle;

            if (float32_is_nan(rFn)
                || float32_is_nan(rFm))
                goto unordered;

            if (n_flag)
                rFm ^= 0x80000000;

            /* test for less than condition */
            if (float32_lt_nocheck(rFn, rFm))
                flags |= CC_NEGATIVE;

            /* test for equal condition */
            if (float32_eq_nocheck(rFn, rFm))
                flags |= CC_ZERO;

            /* test for greater than or equal condition */
            if (float32_lt_nocheck(rFm, rFn))
                flags |= CC_CARRY;
        } else {
            /* Promote 32-bit operand to 64 bits.  */
            float64 rFm, rFn;

            rFm = (fpa11->fType[Fm] == typeSingle) ?
                float32_to_float64(fpa11->fpreg[Fm].fSingle)
                : fpa11->fpreg[Fm].fDouble;

            rFn = (fpa11->fType[Fn] == typeSingle) ?
                float32_to_float64(fpa11->fpreg[Fn].fSingle)
                : fpa11->fpreg[Fn].fDouble;

            if (float64_is_nan(rFn)
                || float64_is_nan(rFm))
                goto unordered;

            if (n_flag)
                rFm ^= 0x8000000000000000ULL;

            /* test for less than condition */
            if (float64_lt_nocheck(rFn, rFm))
                flags |= CC_NEGATIVE;

            /* test for equal condition */
            if (float64_eq_nocheck(rFn, rFm))
                flags |= CC_ZERO;

            /* test for greater than or equal condition */
            if (float64_lt_nocheck(rFm, rFn))
                flags |= CC_CARRY;
        }
    }

#endif

    writeConditionCodes(flags);

    return 1;

      unordered:
    /* ?? The FPA data sheet is pretty vague about this, in particular
       about whether the non-E comparisons can ever raise exceptions.
       This implementation is based on a combination of what it says in
       the data sheet, observation of how the Acorn emulator actually
       behaves (and how programs expect it to) and guesswork.  */
    flags |= CC_OVERFLOW;
    flags &= ~(CC_ZERO | CC_NEGATIVE);

    if (BIT_AC & readFPSR())
        flags |= CC_CARRY;

    if (e_flag)
        float_raise(float_flag_invalid);

    writeConditionCodes(flags);
    return 1;
}
예제 #3
0
unsigned int SingleCPDO(const unsigned int opcode)
{
   FPA11 *fpa11 = GET_FPA11();
   float32 rFm, rFn = float32_zero;
   unsigned int Fd, Fm, Fn, nRc = 1;

   Fm = getFm(opcode);
   if (CONSTANT_FM(opcode))
   {
     rFm = getSingleConstant(Fm);
   }
   else
   {
     switch (fpa11->fType[Fm])
     {
        case typeSingle:
          rFm = fpa11->fpreg[Fm].fSingle;
        break;

        default: return 0;
     }
   }

   if (!MONADIC_INSTRUCTION(opcode))
   {
      Fn = getFn(opcode);
      switch (fpa11->fType[Fn])
      {
        case typeSingle:
          rFn = fpa11->fpreg[Fn].fSingle;
        break;

        default: return 0;
      }
   }

   Fd = getFd(opcode);
   switch (opcode & MASK_ARITHMETIC_OPCODE)
   {
      /* dyadic opcodes */
      case ADF_CODE:
         fpa11->fpreg[Fd].fSingle = float32_add(rFn,rFm, &fpa11->fp_status);
      break;

      case MUF_CODE:
      case FML_CODE:
        fpa11->fpreg[Fd].fSingle = float32_mul(rFn,rFm, &fpa11->fp_status);
      break;

      case SUF_CODE:
         fpa11->fpreg[Fd].fSingle = float32_sub(rFn,rFm, &fpa11->fp_status);
      break;

      case RSF_CODE:
         fpa11->fpreg[Fd].fSingle = float32_sub(rFm,rFn, &fpa11->fp_status);
      break;

      case DVF_CODE:
      case FDV_CODE:
         fpa11->fpreg[Fd].fSingle = float32_div(rFn,rFm, &fpa11->fp_status);
      break;

      case RDF_CODE:
      case FRD_CODE:
         fpa11->fpreg[Fd].fSingle = float32_div(rFm,rFn, &fpa11->fp_status);
      break;

#if 0
      case POW_CODE:
         fpa11->fpreg[Fd].fSingle = float32_pow(rFn,rFm);
      break;

      case RPW_CODE:
         fpa11->fpreg[Fd].fSingle = float32_pow(rFm,rFn);
      break;
#endif

      case RMF_CODE:
         fpa11->fpreg[Fd].fSingle = float32_rem(rFn,rFm, &fpa11->fp_status);
      break;

#if 0
      case POL_CODE:
         fpa11->fpreg[Fd].fSingle = float32_pol(rFn,rFm);
      break;
#endif

      /* monadic opcodes */
      case MVF_CODE:
         fpa11->fpreg[Fd].fSingle = rFm;
      break;

      case MNF_CODE:
         fpa11->fpreg[Fd].fSingle = float32_chs(rFm);
      break;

      case ABS_CODE:
         fpa11->fpreg[Fd].fSingle = float32_abs(rFm);
      break;

      case RND_CODE:
      case URD_CODE:
         fpa11->fpreg[Fd].fSingle = float32_round_to_int(rFm, &fpa11->fp_status);
      break;

      case SQT_CODE:
         fpa11->fpreg[Fd].fSingle = float32_sqrt(rFm, &fpa11->fp_status);
      break;

#if 0
      case LOG_CODE:
         fpa11->fpreg[Fd].fSingle = float32_log(rFm);
      break;

      case LGN_CODE:
         fpa11->fpreg[Fd].fSingle = float32_ln(rFm);
      break;

      case EXP_CODE:
         fpa11->fpreg[Fd].fSingle = float32_exp(rFm);
      break;

      case SIN_CODE:
         fpa11->fpreg[Fd].fSingle = float32_sin(rFm);
      break;

      case COS_CODE:
         fpa11->fpreg[Fd].fSingle = float32_cos(rFm);
      break;

      case TAN_CODE:
         fpa11->fpreg[Fd].fSingle = float32_tan(rFm);
      break;

      case ASN_CODE:
         fpa11->fpreg[Fd].fSingle = float32_arcsin(rFm);
      break;

      case ACS_CODE:
         fpa11->fpreg[Fd].fSingle = float32_arccos(rFm);
      break;

      case ATN_CODE:
         fpa11->fpreg[Fd].fSingle = float32_arctan(rFm);
      break;
#endif

      case NRM_CODE:
      break;

      default:
      {
        nRc = 0;
      }
   }

   if (0 != nRc) fpa11->fType[Fd] = typeSingle;
   return nRc;
}
예제 #4
0
float32 float32_log(float32 rFm)
{
  return float32_div(float32_ln(rFm),getSingleConstant(7));
}