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; }
/*@-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; }