コード例 #1
0
ファイル: floatnum.c プロジェクト: Acidburn0zzz/yasm
yasm_floatnum *
yasm_floatnum_create(const char *str)
{
    yasm_floatnum *flt;
    int dec_exponent, dec_exp_add;      /* decimal (powers of 10) exponent */
    int POT_index;
    wordptr operand[2];
    int sig_digits;
    int decimal_pt;
    boolean carry;

    flt = yasm_xmalloc(sizeof(yasm_floatnum));

    flt->mantissa = BitVector_Create(MANT_BITS, TRUE);

    /* allocate and initialize calculation variables */
    operand[0] = BitVector_Create(MANT_BITS, TRUE);
    operand[1] = BitVector_Create(MANT_BITS, TRUE);
    dec_exponent = 0;
    sig_digits = 0;
    decimal_pt = 1;

    /* set initial flags to 0 */
    flt->flags = 0;

    /* check for + or - character and skip */
    if (*str == '-') {
        flt->sign = 1;
        str++;
    } else if (*str == '+') {
        flt->sign = 0;
        str++;
    } else
        flt->sign = 0;

    /* eliminate any leading zeros (which do not count as significant digits) */
    while (*str == '0')
        str++;

    /* When we reach the end of the leading zeros, first check for a decimal
     * point.  If the number is of the form "0---0.0000" we need to get rid
     * of the zeros after the decimal point and not count them as significant
     * digits.
     */
    if (*str == '.') {
        str++;
        while (*str == '0') {
            str++;
            dec_exponent--;
        }
    } else {
        /* The number is of the form "yyy.xxxx" (where y <> 0). */
        while (isdigit(*str)) {
            /* See if we've processed more than the max significant digits: */
            if (sig_digits < MANT_SIGDIGITS) {
                /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
                BitVector_shift_left(flt->mantissa, 0);
                BitVector_Copy(operand[0], flt->mantissa);
                BitVector_Move_Left(flt->mantissa, 2);
                carry = 0;
                BitVector_add(operand[1], operand[0], flt->mantissa, &carry);

                /* Add in current digit */
                BitVector_Empty(operand[0]);
                BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
                carry = 0;
                BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
            } else {
                /* Can't integrate more digits with mantissa, so instead just
                 * raise by a power of ten.
                 */
                dec_exponent++;
            }
            sig_digits++;
            str++;
        }

        if (*str == '.')
            str++;
        else
            decimal_pt = 0;
    }

    if (decimal_pt) {
        /* Process the digits to the right of the decimal point. */
        while (isdigit(*str)) {
            /* See if we've processed more than 19 significant digits: */
            if (sig_digits < 19) {
                /* Raise by a power of ten */
                dec_exponent--;

                /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
                BitVector_shift_left(flt->mantissa, 0);
                BitVector_Copy(operand[0], flt->mantissa);
                BitVector_Move_Left(flt->mantissa, 2);
                carry = 0;
                BitVector_add(operand[1], operand[0], flt->mantissa, &carry);

                /* Add in current digit */
                BitVector_Empty(operand[0]);
                BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
                carry = 0;
                BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
            }
            sig_digits++;
            str++;
        }
    }

    if (*str == 'e' || *str == 'E') {
        str++;
        /* We just saw the "E" character, now read in the exponent value and
         * add it into dec_exponent.
         */
        dec_exp_add = 0;
        sscanf(str, "%d", &dec_exp_add);
        dec_exponent += dec_exp_add;
    }

    /* Free calculation variables. */
    BitVector_Destroy(operand[1]);
    BitVector_Destroy(operand[0]);

    /* Normalize the number, checking for 0 first. */
    if (BitVector_is_empty(flt->mantissa)) {
        /* Mantissa is 0, zero exponent too. */
        flt->exponent = 0;
        /* Set zero flag so output functions don't see 0 value as underflow. */
        flt->flags |= FLAG_ISZERO;
        /* Return 0 value. */
        return flt;
    }
    /* Exponent if already norm. */
    flt->exponent = (unsigned short)(0x7FFF+(MANT_BITS-1));
    floatnum_normalize(flt);

    /* The number is normalized.  Now multiply by 10 the number of times
     * specified in DecExponent.  This uses the power of ten tables to speed
     * up this operation (and make it more accurate).
     */
    if (dec_exponent > 0) {
        POT_index = 0;
        /* Until we hit 1.0 or finish exponent or overflow */
        while ((POT_index < 14) && (dec_exponent != 0) &&
               (flt->exponent != EXP_INF)) {
            /* Find the first power of ten in the table which is just less than
             * the exponent.
             */
            while (dec_exponent < POT_TableP[POT_index].dec_exponent)
                POT_index++;

            if (POT_index < 14) {
                /* Subtract out what we're multiplying in from exponent */
                dec_exponent -= POT_TableP[POT_index].dec_exponent;

                /* Multiply by current power of 10 */
                floatnum_mul(flt, &POT_TableP[POT_index].f);
            }
        }
    } else if (dec_exponent < 0) {
        POT_index = 0;
        /* Until we hit 1.0 or finish exponent or underflow */
        while ((POT_index < 14) && (dec_exponent != 0) &&
               (flt->exponent != EXP_ZERO)) {
            /* Find the first power of ten in the table which is just less than
             * the exponent.
             */
            while (dec_exponent > POT_TableN[POT_index].dec_exponent)
                POT_index++;

            if (POT_index < 14) {
                /* Subtract out what we're multiplying in from exponent */
                dec_exponent -= POT_TableN[POT_index].dec_exponent;

                /* Multiply by current power of 10 */
                floatnum_mul(flt, &POT_TableN[POT_index].f);
            }
        }
    }

    /* Round the result. (Don't round underflow or overflow).  Also don't
     * increment if this would cause the mantissa to wrap.
     */
    if ((flt->exponent != EXP_INF) && (flt->exponent != EXP_ZERO) &&
        !BitVector_is_full(flt->mantissa))
        BitVector_increment(flt->mantissa);

    return flt;
}
コード例 #2
0
ファイル: intnum.c プロジェクト: kstephens/yasm
/*@-nullderef -nullpass -branchstate@*/
int
yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op, yasm_intnum *operand)
{
    boolean carry = 0;
    wordptr op1, op2 = NULL;
    N_int count;

    /* Always do computations with in full bit vector.
     * Bit vector results must be calculated through intermediate storage.
     */
    op1 = intnum_tobv(op1static, acc);
    if (operand)
        op2 = intnum_tobv(op2static, operand);

    if (!operand && op != YASM_EXPR_NEG && op != YASM_EXPR_NOT &&
        op != YASM_EXPR_LNOT) {
        yasm_error_set(YASM_ERROR_ARITHMETIC,
                       N_("operation needs an operand"));
        BitVector_Empty(result);
        return 1;
    }

    /* A operation does a bitvector computation if result is allocated. */
    switch (op) {
        case YASM_EXPR_ADD:
            BitVector_add(result, op1, op2, &carry);
            break;
        case YASM_EXPR_SUB:
            BitVector_sub(result, op1, op2, &carry);
            break;
        case YASM_EXPR_MUL:
            BitVector_Multiply(result, op1, op2);
            break;
        case YASM_EXPR_DIV:
            /* TODO: make sure op1 and op2 are unsigned */
            if (BitVector_is_empty(op2)) {
                yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
                BitVector_Empty(result);
                return 1;
            } else
                BitVector_Divide(result, op1, op2, spare);
            break;
        case YASM_EXPR_SIGNDIV:
            if (BitVector_is_empty(op2)) {
                yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
                BitVector_Empty(result);
                return 1;
            } else
                BitVector_Divide(result, op1, op2, spare);
            break;
        case YASM_EXPR_MOD:
            /* TODO: make sure op1 and op2 are unsigned */
            if (BitVector_is_empty(op2)) {
                yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
                BitVector_Empty(result);
                return 1;
            } else
                BitVector_Divide(spare, op1, op2, result);
            break;
        case YASM_EXPR_SIGNMOD:
            if (BitVector_is_empty(op2)) {
                yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
                BitVector_Empty(result);
                return 1;
            } else
                BitVector_Divide(spare, op1, op2, result);
            break;
        case YASM_EXPR_NEG:
            BitVector_Negate(result, op1);
            break;
        case YASM_EXPR_NOT:
            Set_Complement(result, op1);
            break;
        case YASM_EXPR_OR:
            Set_Union(result, op1, op2);
            break;
        case YASM_EXPR_AND:
            Set_Intersection(result, op1, op2);
            break;
        case YASM_EXPR_XOR:
            Set_ExclusiveOr(result, op1, op2);
            break;
        case YASM_EXPR_XNOR:
            Set_ExclusiveOr(result, op1, op2);
            Set_Complement(result, result);
            break;
        case YASM_EXPR_NOR:
            Set_Union(result, op1, op2);
            Set_Complement(result, result);
            break;
        case YASM_EXPR_SHL:
            if (operand->type == INTNUM_L && operand->val.l >= 0) {
                BitVector_Copy(result, op1);
                BitVector_Move_Left(result, (N_int)operand->val.l);
            } else      /* don't even bother, just zero result */
                BitVector_Empty(result);
            break;
        case YASM_EXPR_SHR:
            if (operand->type == INTNUM_L && operand->val.l >= 0) {
                BitVector_Copy(result, op1);
                carry = BitVector_msb_(op1);
                count = (N_int)operand->val.l;
                while (count-- > 0)
                    BitVector_shift_right(result, carry);
            } else      /* don't even bother, just zero result */
                BitVector_Empty(result);
            break;
        case YASM_EXPR_LOR:
            BitVector_Empty(result);
            BitVector_LSB(result, !BitVector_is_empty(op1) ||
                          !BitVector_is_empty(op2));
            break;
        case YASM_EXPR_LAND:
            BitVector_Empty(result);
            BitVector_LSB(result, !BitVector_is_empty(op1) &&
                          !BitVector_is_empty(op2));
            break;
        case YASM_EXPR_LNOT:
            BitVector_Empty(result);
            BitVector_LSB(result, BitVector_is_empty(op1));
            break;
        case YASM_EXPR_LXOR:
            BitVector_Empty(result);
            BitVector_LSB(result, !BitVector_is_empty(op1) ^
                          !BitVector_is_empty(op2));
            break;
        case YASM_EXPR_LXNOR:
            BitVector_Empty(result);
            BitVector_LSB(result, !(!BitVector_is_empty(op1) ^
                          !BitVector_is_empty(op2)));
            break;
        case YASM_EXPR_LNOR:
            BitVector_Empty(result);
            BitVector_LSB(result, !(!BitVector_is_empty(op1) ||
                          !BitVector_is_empty(op2)));
            break;
        case YASM_EXPR_EQ:
            BitVector_Empty(result);
            BitVector_LSB(result, BitVector_equal(op1, op2));
            break;
        case YASM_EXPR_LT:
            BitVector_Empty(result);
            BitVector_LSB(result, BitVector_Compare(op1, op2) < 0);
            break;
        case YASM_EXPR_GT:
            BitVector_Empty(result);
            BitVector_LSB(result, BitVector_Compare(op1, op2) > 0);
            break;
        case YASM_EXPR_LE:
            BitVector_Empty(result);
            BitVector_LSB(result, BitVector_Compare(op1, op2) <= 0);
            break;
        case YASM_EXPR_GE:
            BitVector_Empty(result);
            BitVector_LSB(result, BitVector_Compare(op1, op2) >= 0);
            break;
        case YASM_EXPR_NE:
            BitVector_Empty(result);
            BitVector_LSB(result, !BitVector_equal(op1, op2));
            break;
        case YASM_EXPR_SEG:
            yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
                           "SEG");
            break;
        case YASM_EXPR_WRT:
            yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
                           "WRT");
            break;
        case YASM_EXPR_SEGOFF:
            yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
                           ":");
            break;
        case YASM_EXPR_IDENT:
            if (result)
                BitVector_Copy(result, op1);
            break;
        default:
            yasm_error_set(YASM_ERROR_ARITHMETIC,
                           N_("invalid operation in intnum calculation"));
            BitVector_Empty(result);
            return 1;
    }

    /* Try to fit the result into 32 bits if possible */
    if (acc->type == INTNUM_BV)
        BitVector_Destroy(acc->val.bv);
    intnum_frombv(acc, result);
    return 0;
}