int yasm_intnum_in_range(const yasm_intnum *intn, long low, long high) { wordptr val = intnum_tobv(result, intn); wordptr lval = op1static; wordptr hval = op2static; /* Convert high and low to bitvects */ BitVector_Empty(lval); if (low >= 0) BitVector_Chunk_Store(lval, 32, 0, (unsigned long)low); else { BitVector_Chunk_Store(lval, 32, 0, (unsigned long)(-low)); BitVector_Negate(lval, lval); } BitVector_Empty(hval); if (high >= 0) BitVector_Chunk_Store(hval, 32, 0, (unsigned long)high); else { BitVector_Chunk_Store(hval, 32, 0, (unsigned long)(-high)); BitVector_Negate(hval, hval); } /* Compare! */ return (BitVector_Compare(val, lval) >= 0 && BitVector_Compare(val, hval) <= 0); }
/* If intnum is a BV, returns its bitvector directly. * If not, converts into passed bv and returns that instead. */ static wordptr intnum_tobv(/*@returned@*/ wordptr bv, const yasm_intnum *intn) { if (intn->type == INTNUM_BV) return intn->val.bv; BitVector_Empty(bv); if (intn->val.l >= 0) BitVector_Chunk_Store(bv, 32, 0, (unsigned long)intn->val.l); else { BitVector_Chunk_Store(bv, 32, 0, (unsigned long)-intn->val.l); BitVector_Negate(bv, bv); } return bv; }
yasm_intnum * yasm_intnum_create_sized(unsigned char *ptr, int sign, size_t srcsize, int bigendian) { yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum)); unsigned long i = 0; if (srcsize*8 > BITVECT_NATIVE_SIZE) yasm_error_set(YASM_ERROR_OVERFLOW, N_("Numeric constant too large for internal format")); /* Read the buffer into a bitvect */ BitVector_Empty(conv_bv); if (bigendian) { /* TODO */ yasm_internal_error(N_("big endian not implemented")); } else { for (i = 0; i < srcsize; i++) BitVector_Chunk_Store(conv_bv, 8, i*8, ptr[i]); } /* Sign extend if needed */ if (srcsize*8 < BITVECT_NATIVE_SIZE && sign && (ptr[i-1] & 0x80) == 0x80) BitVector_Interval_Fill(conv_bv, i*8, BITVECT_NATIVE_SIZE-1); intnum_frombv(intn, conv_bv); return intn; }
yasm_intnum * yasm_intnum_create_leb128(const unsigned char *ptr, int sign, unsigned long *size) { yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum)); const unsigned char *ptr_orig = ptr; unsigned long i = 0; BitVector_Empty(conv_bv); for (;;) { BitVector_Chunk_Store(conv_bv, 7, i, *ptr); i += 7; if ((*ptr & 0x80) != 0x80) break; ptr++; } *size = (unsigned long)(ptr-ptr_orig)+1; if(i > BITVECT_NATIVE_SIZE) yasm_error_set(YASM_ERROR_OVERFLOW, N_("Numeric constant too large for internal format")); else if (sign && (*ptr & 0x40) == 0x40) BitVector_Interval_Fill(conv_bv, i, BITVECT_NATIVE_SIZE-1); intnum_frombv(intn, conv_bv); return intn; }
unsigned long yasm_size_sleb128(long v) { wordptr val = op1static; if (v == 0) return 1; BitVector_Empty(val); if (v >= 0) BitVector_Chunk_Store(val, 32, 0, (unsigned long)v); else { BitVector_Chunk_Store(val, 32, 0, (unsigned long)(-v)); BitVector_Negate(val, val); } return size_leb128(val, 1); }
unsigned long yasm_get_sleb128(long v, unsigned char *ptr) { wordptr val = op1static; /* Shortcut 0 */ if (v == 0) { *ptr = 0; return 1; } BitVector_Empty(val); if (v >= 0) BitVector_Chunk_Store(val, 32, 0, (unsigned long)v); else { BitVector_Chunk_Store(val, 32, 0, (unsigned long)(-v)); BitVector_Negate(val, val); } return get_leb128(val, ptr, 1); }
unsigned long yasm_size_uleb128(unsigned long v) { wordptr val = op1static; if (v == 0) return 1; BitVector_Empty(val); BitVector_Chunk_Store(val, 32, 0, v); return size_leb128(val, 0); }
unsigned long yasm_get_uleb128(unsigned long v, unsigned char *ptr) { wordptr val = op1static; /* Shortcut 0 */ if (v == 0) { *ptr = 0; return 1; } BitVector_Empty(val); BitVector_Chunk_Store(val, 32, 0, v); return get_leb128(val, ptr, 0); }
yasm_intnum * yasm_intnum_create_charconst_tasm(const char *str) { yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum)); size_t len = strlen(str); size_t i; 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; } /* tasm uses big endian notation */ i = 0; switch (len) { case 3: intn->val.l |= ((unsigned long)str[i++]) & 0xff; intn->val.l <<= 8; /*@fallthrough@*/ case 2: intn->val.l |= ((unsigned long)str[i++]) & 0xff; intn->val.l <<= 8; /*@fallthrough@*/ case 1: intn->val.l |= ((unsigned long)str[i++]) & 0xff; case 0: break; default: /* >=32 bit conversion */ while (i < len) { BitVector_Chunk_Store(conv_bv, 8, (len-i-1)*8, ((unsigned long)str[i]) & 0xff); i++; } intn->val.bv = BitVector_Clone(conv_bv); } return intn; }
void yasm_intnum_set_uint(yasm_intnum *intn, unsigned long val) { if (val > LONG_MAX) { if (intn->type != INTNUM_BV) { intn->val.bv = BitVector_Create(BITVECT_NATIVE_SIZE, TRUE); intn->type = INTNUM_BV; } BitVector_Chunk_Store(intn->val.bv, 32, 0, val); } else { if (intn->type == INTNUM_BV) { BitVector_Destroy(intn->val.bv); intn->type = INTNUM_L; } intn->val.l = (long)val; } }
yasm_intnum * yasm_intnum_create_uint(unsigned long i) { yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum)); if (i > LONG_MAX) { /* Too big, store as bitvector */ intn->val.bv = BitVector_Create(BITVECT_NATIVE_SIZE, TRUE); intn->type = INTNUM_BV; BitVector_Chunk_Store(intn->val.bv, 32, 0, i); } else { intn->val.l = (long)i; intn->type = INTNUM_L; } return intn; }
/* 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; }
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; }