static void floatnum_normalize(yasm_floatnum *flt) { long norm_amt; if (BitVector_is_empty(flt->mantissa)) { flt->exponent = 0; return; } /* 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-1)-Set_Max(flt->mantissa); if (norm_amt > (long)flt->exponent) norm_amt = (long)flt->exponent; BitVector_Move_Left(flt->mantissa, (N_int)norm_amt); flt->exponent -= (unsigned short)norm_amt; }
/*@-usedef -compdef -uniondef@*/ yasm_intnum * yasm_intnum_create_charconst_nasm(const char *str) { yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum)); size_t len = strlen(str); if(len*8 > BITVECT_NATIVE_SIZE) yasm_error_set(YASM_ERROR_OVERFLOW, N_("Character constant too large for internal format")); /* be conservative in choosing bitvect in case MSB is set */ if (len > 3) { BitVector_Empty(conv_bv); intn->type = INTNUM_BV; } else { intn->val.l = 0; intn->type = INTNUM_L; } switch (len) { case 3: intn->val.l |= ((unsigned long)str[2]) & 0xff; intn->val.l <<= 8; /*@fallthrough@*/ case 2: intn->val.l |= ((unsigned long)str[1]) & 0xff; intn->val.l <<= 8; /*@fallthrough@*/ case 1: intn->val.l |= ((unsigned long)str[0]) & 0xff; case 0: break; default: /* >=32 bit conversion */ while (len) { BitVector_Move_Left(conv_bv, 8); BitVector_Chunk_Store(conv_bv, 8, 0, ((unsigned long)str[--len]) & 0xff); } intn->val.bv = BitVector_Clone(conv_bv); } return intn; }
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; }
/* 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); }
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); }
/*@-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; }