Пример #1
0
void
yasm_intnum_set(yasm_intnum *intn, const yasm_intnum *val)
{
    if (intn->type == val->type) {
        switch (val->type) {
            case INTNUM_L:
                intn->val.l = val->val.l;
                break;
            case INTNUM_BV:
                BitVector_Copy(intn->val.bv, val->val.bv);
                break;
        }
    } else {
        switch (val->type) {
            case INTNUM_L:
                BitVector_Destroy(intn->val.bv);
                intn->val.l = val->val.l;
                break;
            case INTNUM_BV:
                intn->val.bv = BitVector_Clone(val->val.bv);
                break;
        }
        intn->type = val->type;
    }
}
Пример #2
0
/* Return 1 if okay size, 0 if not */
int
yasm_intnum_check_size(const yasm_intnum *intn, size_t size, size_t rshift,
                       int rangetype)
{
    wordptr val;

    /* If not already a bitvect, convert value to a bitvect */
    if (intn->type == INTNUM_BV) {
        if (rshift > 0) {
            val = conv_bv;
            BitVector_Copy(val, intn->val.bv);
        } else
            val = intn->val.bv;
    } else
        val = intnum_tobv(conv_bv, intn);

    if (size >= BITVECT_NATIVE_SIZE)
        return 1;

    if (rshift > 0) {
        int carry_in = BitVector_msb_(val);
        while (rshift-- > 0)
            BitVector_shift_right(val, carry_in);
    }

    if (rangetype > 0) {
        if (BitVector_msb_(val)) {
            /* it's negative */
            int retval;

            BitVector_Negate(conv_bv, val);
            BitVector_dec(conv_bv, conv_bv);
            retval = Set_Max(conv_bv) < (long)size-1;

            return retval;
        }
        
        if (rangetype == 1)
            size--;
    }
    return (Set_Max(val) < (long)size);
}
Пример #3
0
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;
}
Пример #4
0
/* acc *= op */
static void
floatnum_mul(yasm_floatnum *acc, const yasm_floatnum *op)
{
    long expon;
    wordptr product, op1, op2;
    long norm_amt;

    /* Compute the new sign */
    acc->sign ^= op->sign;

    /* Check for multiply by 0 */
    if (BitVector_is_empty(acc->mantissa) || BitVector_is_empty(op->mantissa)) {
        BitVector_Empty(acc->mantissa);
        acc->exponent = EXP_ZERO;
        return;
    }

    /* Add exponents, checking for overflow/underflow. */
    expon = (((int)acc->exponent)-EXP_BIAS) + (((int)op->exponent)-EXP_BIAS);
    expon += EXP_BIAS;
    if (expon > EXP_MAX) {
        /* Overflow; return infinity. */
        BitVector_Empty(acc->mantissa);
        acc->exponent = EXP_INF;
        return;
    } else if (expon < EXP_MIN) {
        /* Underflow; return zero. */
        BitVector_Empty(acc->mantissa);
        acc->exponent = EXP_ZERO;
        return;
    }

    /* Add one to the final exponent, as the multiply shifts one extra time. */
    acc->exponent = (unsigned short)(expon+1);

    /* Allocate space for the multiply result */
    product = BitVector_Create((N_int)((MANT_BITS+1)*2), FALSE);

    /* Allocate 1-bit-longer fields to force the operands to be unsigned */
    op1 = BitVector_Create((N_int)(MANT_BITS+1), FALSE);
    op2 = BitVector_Create((N_int)(MANT_BITS+1), FALSE);

    /* Make the operands unsigned after copying from original operands */
    BitVector_Copy(op1, acc->mantissa);
    BitVector_MSB(op1, 0);
    BitVector_Copy(op2, op->mantissa);
    BitVector_MSB(op2, 0);

    /* Compute the product of the mantissas */
    BitVector_Multiply(product, op1, op2);

    /* Normalize the product.  Note: we know the product is non-zero because
     * both of the original operands were non-zero.
     *
     * Look for the highest set bit, shift to make it the MSB, and adjust
     * exponent.  Don't let exponent go negative.
     */
    norm_amt = (MANT_BITS*2-1)-Set_Max(product);
    if (norm_amt > (long)acc->exponent)
        norm_amt = (long)acc->exponent;
    BitVector_Move_Left(product, (N_int)norm_amt);
    acc->exponent -= (unsigned short)norm_amt;

    /* Store the highest bits of the result */
    BitVector_Interval_Copy(acc->mantissa, product, 0, MANT_BITS, MANT_BITS);

    /* Free allocated variables */
    BitVector_Destroy(product);
    BitVector_Destroy(op1);
    BitVector_Destroy(op2);
}
Пример #5
0
void
yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr,
                      size_t destsize, size_t valsize, int shift,
                      int bigendian, int warn)
{
    wordptr op1 = op1static, op2;
    unsigned char *buf;
    unsigned int len;
    size_t rshift = shift < 0 ? (size_t)(-shift) : 0;
    int carry_in;

    /* Currently don't support destinations larger than our native size */
    if (destsize*8 > BITVECT_NATIVE_SIZE)
        yasm_internal_error(N_("destination too large"));

    /* General size warnings */
    if (warn<0 && !yasm_intnum_check_size(intn, valsize, rshift, 1))
        yasm_warn_set(YASM_WARN_GENERAL,
                      N_("value does not fit in signed %d bit field"),
                      valsize);
    if (warn>0 && !yasm_intnum_check_size(intn, valsize, rshift, 2))
        yasm_warn_set(YASM_WARN_GENERAL,
                      N_("value does not fit in %d bit field"), valsize);

    /* Read the original data into a bitvect */
    if (bigendian) {
        /* TODO */
        yasm_internal_error(N_("big endian not implemented"));
    } else
        BitVector_Block_Store(op1, ptr, (N_int)destsize);

    /* If not already a bitvect, convert value to be written to a bitvect */
    op2 = intnum_tobv(op2static, intn);

    /* Check low bits if right shifting and warnings enabled */
    if (warn && rshift > 0) {
        BitVector_Copy(conv_bv, op2);
        BitVector_Move_Left(conv_bv, (N_int)(BITVECT_NATIVE_SIZE-rshift));
        if (!BitVector_is_empty(conv_bv))
            yasm_warn_set(YASM_WARN_GENERAL,
                          N_("misaligned value, truncating to boundary"));
    }

    /* Shift right if needed */
    if (rshift > 0) {
        carry_in = BitVector_msb_(op2);
        while (rshift-- > 0)
            BitVector_shift_right(op2, carry_in);
        shift = 0;
    }

    /* Write the new value into the destination bitvect */
    BitVector_Interval_Copy(op1, op2, (unsigned int)shift, 0, (N_int)valsize);

    /* Write out the new data */
    buf = BitVector_Block_Read(op1, &len);
    if (bigendian) {
        /* TODO */
        yasm_internal_error(N_("big endian not implemented"));
    } else
        memcpy(ptr, buf, destsize);
    yasm_xfree(buf);
}
Пример #6
0
/*@-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;
}