示例#1
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);
}
示例#2
0
/* Function used by conversion routines to actually perform the conversion.
 *
 * ptr -> the array to return the little-endian floating point value into.
 * flt -> the floating point value to convert.
 * byte_size -> the size in bytes of the output format.
 * mant_bits -> the size in bits of the output mantissa.
 * implicit1 -> does the output format have an implicit 1? 1=yes, 0=no.
 * exp_bits -> the size in bits of the output exponent.
 *
 * Returns 0 on success, 1 if overflow, -1 if underflow.
 */
static int
floatnum_get_common(const yasm_floatnum *flt, /*@out@*/ unsigned char *ptr,
                    N_int byte_size, N_int mant_bits, int implicit1,
                    N_int exp_bits)
{
    long exponent = (long)flt->exponent;
    wordptr output;
    charptr buf;
    unsigned int len;
    unsigned int overflow = 0, underflow = 0;
    int retval = 0;
    long exp_bias = (1<<(exp_bits-1))-1;
    long exp_inf = (1<<exp_bits)-1;

    output = BitVector_Create(byte_size*8, TRUE);

    /* copy mantissa */
    BitVector_Interval_Copy(output, flt->mantissa, 0,
                            (N_int)((MANT_BITS-implicit1)-mant_bits),
                            mant_bits);

    /* round mantissa */
    if (BitVector_bit_test(flt->mantissa, (MANT_BITS-implicit1)-(mant_bits+1)))
        BitVector_increment(output);

    if (BitVector_bit_test(output, mant_bits)) {
        /* overflowed, so zero mantissa (and set explicit bit if necessary) */
        BitVector_Empty(output);
        BitVector_Bit_Copy(output, mant_bits-1, !implicit1);
        /* and up the exponent (checking for overflow) */
        if (exponent+1 >= EXP_INF)
            overflow = 1;
        else
            exponent++;
    }

    /* adjust the exponent to the output bias, checking for overflow */
    exponent -= EXP_BIAS-exp_bias;
    if (exponent >= exp_inf)
        overflow = 1;
    else if (exponent <= 0)
        underflow = 1;

    /* underflow and overflow both set!? */
    if (underflow && overflow)
        yasm_internal_error(N_("Both underflow and overflow set"));

    /* check for underflow or overflow and set up appropriate output */
    if (underflow) {
        BitVector_Empty(output);
        exponent = 0;
        if (!(flt->flags & FLAG_ISZERO))
            retval = -1;
    } else if (overflow) {
        BitVector_Empty(output);
        exponent = exp_inf;
        retval = 1;
    }

    /* move exponent into place */
    BitVector_Chunk_Store(output, exp_bits, mant_bits, (N_long)exponent);

    /* merge in sign bit */
    BitVector_Bit_Copy(output, byte_size*8-1, flt->sign);

    /* get little-endian bytes */
    buf = BitVector_Block_Read(output, &len);
    if (len < byte_size)
        yasm_internal_error(
            N_("Byte length of BitVector does not match bit length"));

    /* copy to output */
    memcpy(ptr, buf, byte_size*sizeof(unsigned char));

    /* free allocated resources */
    yasm_xfree(buf);

    BitVector_Destroy(output);

    return retval;
}
示例#3
0
文件: intnum.c 项目: kstephens/yasm
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);
}