blob: b4d82821b76c5009a788ad5ac642240a541c8abb [file] [log] [blame]
/*
* Integer number functions.
*
* Copyright (C) 2001 Peter Johnson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#define YASM_LIB_INTERNAL
#include "util.h"
/*@unused@*/ RCSID("$Id$");
#include <ctype.h>
#include <limits.h>
#include "coretype.h"
#include "bitvect.h"
#include "file.h"
#include "errwarn.h"
#include "intnum.h"
/* "Native" "word" size for intnum calculations. */
#define BITVECT_NATIVE_SIZE 128
struct yasm_intnum {
union val {
unsigned long ul; /* integer value (for integers <=32 bits) */
wordptr bv; /* bit vector (for integers >32 bits) */
} val;
enum { INTNUM_UL, INTNUM_BV } type;
unsigned char origsize; /* original (parsed) size, in bits */
};
/* static bitvect used for conversions */
static /*@only@*/ wordptr conv_bv;
/* static bitvects used for computation */
static /*@only@*/ wordptr result, spare, op1static, op2static;
static /*@only@*/ BitVector_from_Dec_static_data *from_dec_data;
void
yasm_intnum_initialize(void)
{
conv_bv = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
result = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
spare = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
op1static = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
op2static = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
from_dec_data = BitVector_from_Dec_static_Boot(BITVECT_NATIVE_SIZE);
}
void
yasm_intnum_cleanup(void)
{
BitVector_from_Dec_static_Shutdown(from_dec_data);
BitVector_Destroy(op2static);
BitVector_Destroy(op1static);
BitVector_Destroy(spare);
BitVector_Destroy(result);
BitVector_Destroy(conv_bv);
}
yasm_intnum *
yasm_intnum_create_dec(char *str, unsigned long line)
{
yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
intn->origsize = 0; /* no reliable way to figure this out */
if (BitVector_from_Dec_static(from_dec_data, conv_bv,
(unsigned char *)str) == ErrCode_Ovfl)
yasm__warning(YASM_WARN_GENERAL, line,
N_("Numeric constant too large for internal format"));
if (Set_Max(conv_bv) < 32) {
intn->type = INTNUM_UL;
intn->val.ul = BitVector_Chunk_Read(conv_bv, 32, 0);
} else {
intn->type = INTNUM_BV;
intn->val.bv = BitVector_Clone(conv_bv);
}
return intn;
}
yasm_intnum *
yasm_intnum_create_bin(char *str, unsigned long line)
{
yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
intn->origsize = (unsigned char)strlen(str);
if(intn->origsize > BITVECT_NATIVE_SIZE)
yasm__warning(YASM_WARN_GENERAL, line,
N_("Numeric constant too large for internal format"));
BitVector_from_Bin(conv_bv, (unsigned char *)str);
if (Set_Max(conv_bv) < 32) {
intn->type = INTNUM_UL;
intn->val.ul = BitVector_Chunk_Read(conv_bv, 32, 0);
} else {
intn->type = INTNUM_BV;
intn->val.bv = BitVector_Clone(conv_bv);
}
return intn;
}
yasm_intnum *
yasm_intnum_create_oct(char *str, unsigned long line)
{
yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
intn->origsize = strlen(str)*3;
if(intn->origsize > BITVECT_NATIVE_SIZE)
yasm__warning(YASM_WARN_GENERAL, line,
N_("Numeric constant too large for internal format"));
BitVector_from_Oct(conv_bv, (unsigned char *)str);
if (Set_Max(conv_bv) < 32) {
intn->type = INTNUM_UL;
intn->val.ul = BitVector_Chunk_Read(conv_bv, 32, 0);
} else {
intn->type = INTNUM_BV;
intn->val.bv = BitVector_Clone(conv_bv);
}
return intn;
}
yasm_intnum *
yasm_intnum_create_hex(char *str, unsigned long line)
{
yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
intn->origsize = strlen(str)*4;
if(intn->origsize > BITVECT_NATIVE_SIZE)
yasm__warning(YASM_WARN_GENERAL, line,
N_("Numeric constant too large for internal format"));
BitVector_from_Hex(conv_bv, (unsigned char *)str);
if (Set_Max(conv_bv) < 32) {
intn->type = INTNUM_UL;
intn->val.ul = BitVector_Chunk_Read(conv_bv, 32, 0);
} else {
intn->type = INTNUM_BV;
intn->val.bv = BitVector_Clone(conv_bv);
}
return intn;
}
/*@-usedef -compdef -uniondef@*/
yasm_intnum *
yasm_intnum_create_charconst_nasm(const char *str, unsigned long line)
{
yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
size_t len = strlen(str);
intn->origsize = len*8;
if(intn->origsize > BITVECT_NATIVE_SIZE)
yasm__warning(YASM_WARN_GENERAL, line,
N_("Character constant too large for internal format"));
if (len > 4) {
BitVector_Empty(conv_bv);
intn->type = INTNUM_BV;
} else {
intn->val.ul = 0;
intn->type = INTNUM_UL;
}
switch (len) {
case 4:
intn->val.ul |= (unsigned long)str[3];
intn->val.ul <<= 8;
/*@fallthrough@*/
case 3:
intn->val.ul |= (unsigned long)str[2];
intn->val.ul <<= 8;
/*@fallthrough@*/
case 2:
intn->val.ul |= (unsigned long)str[1];
intn->val.ul <<= 8;
/*@fallthrough@*/
case 1:
intn->val.ul |= (unsigned long)str[0];
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]);
}
intn->val.bv = BitVector_Clone(conv_bv);
}
return intn;
}
/*@=usedef =compdef =uniondef@*/
yasm_intnum *
yasm_intnum_create_uint(unsigned long i)
{
yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
intn->val.ul = i;
intn->type = INTNUM_UL;
intn->origsize = 0;
return intn;
}
yasm_intnum *
yasm_intnum_create_int(long i)
{
yasm_intnum *intn;
/* positive numbers can go through the uint() function */
if (i >= 0)
return yasm_intnum_create_uint((unsigned long)i);
BitVector_Empty(conv_bv);
BitVector_Chunk_Store(conv_bv, 32, 0, (unsigned long)(-i));
BitVector_Negate(conv_bv, conv_bv);
intn = yasm_xmalloc(sizeof(yasm_intnum));
intn->val.bv = BitVector_Clone(conv_bv);
intn->type = INTNUM_BV;
intn->origsize = 0;
return intn;
}
yasm_intnum *
yasm_intnum_create_leb128(const unsigned char *ptr, int sign,
unsigned long *size, unsigned long line)
{
yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
const unsigned char *ptr_orig = ptr;
unsigned long i = 0;
intn->origsize = 0;
BitVector_Empty(conv_bv);
for (;;) {
BitVector_Chunk_Store(conv_bv, 7, i, *ptr);
i += 7;
if ((*ptr & 0x80) != 0x80)
break;
ptr++;
}
*size = (ptr-ptr_orig)+1;
if(i > BITVECT_NATIVE_SIZE)
yasm__warning(YASM_WARN_GENERAL, line,
N_("Numeric constant too large for internal format"));
else if (sign && (*ptr & 0x40) == 0x40)
BitVector_Interval_Fill(conv_bv, i, BITVECT_NATIVE_SIZE-1);
if (Set_Max(conv_bv) < 32) {
intn->type = INTNUM_UL;
intn->val.ul = BitVector_Chunk_Read(conv_bv, 32, 0);
} else {
intn->type = INTNUM_BV;
intn->val.bv = BitVector_Clone(conv_bv);
}
return intn;
}
yasm_intnum *
yasm_intnum_copy(const yasm_intnum *intn)
{
yasm_intnum *n = yasm_xmalloc(sizeof(yasm_intnum));
switch (intn->type) {
case INTNUM_UL:
n->val.ul = intn->val.ul;
break;
case INTNUM_BV:
n->val.bv = BitVector_Clone(intn->val.bv);
break;
}
n->type = intn->type;
n->origsize = intn->origsize;
return n;
}
void
yasm_intnum_destroy(yasm_intnum *intn)
{
if (intn->type == INTNUM_BV)
BitVector_Destroy(intn->val.bv);
yasm_xfree(intn);
}
/*@-nullderef -nullpass -branchstate@*/
void
yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op, yasm_intnum *operand,
unsigned long line)
{
boolean carry = 0;
wordptr op1, op2 = NULL;
/* Always do computations with in full bit vector.
* Bit vector results must be calculated through intermediate storage.
*/
if (acc->type == INTNUM_BV)
op1 = acc->val.bv;
else {
op1 = op1static;
BitVector_Empty(op1);
BitVector_Chunk_Store(op1, 32, 0, acc->val.ul);
}
if (operand) {
if (operand->type == INTNUM_BV)
op2 = operand->val.bv;
else {
op2 = op2static;
BitVector_Empty(op2);
BitVector_Chunk_Store(op2, 32, 0, operand->val.ul);
}
}
if (!operand && op != YASM_EXPR_NEG && op != YASM_EXPR_NOT &&
op != YASM_EXPR_LNOT)
yasm_internal_error(N_("Operation needs an operand"));
/* 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 */
BitVector_Divide(result, op1, op2, spare);
break;
case YASM_EXPR_SIGNDIV:
BitVector_Divide(result, op1, op2, spare);
break;
case YASM_EXPR_MOD:
/* TODO: make sure op1 and op2 are unsigned */
BitVector_Divide(spare, op1, op2, result);
break;
case YASM_EXPR_SIGNMOD:
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_NOR:
Set_Union(result, op1, op2);
Set_Complement(result, result);
break;
case YASM_EXPR_SHL:
if (operand->type == INTNUM_UL) {
BitVector_Copy(result, op1);
BitVector_Move_Left(result, (N_int)operand->val.ul);
} else /* don't even bother, just zero result */
BitVector_Empty(result);
break;
case YASM_EXPR_SHR:
if (operand->type == INTNUM_UL) {
BitVector_Copy(result, op1);
BitVector_Move_Right(result, (N_int)operand->val.ul);
} 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_EQ:
BitVector_Empty(result);
BitVector_LSB(result, BitVector_equal(op1, op2));
break;
case YASM_EXPR_LT:
BitVector_Empty(result);
BitVector_LSB(result, BitVector_Lexicompare(op1, op2) < 0);
break;
case YASM_EXPR_GT:
BitVector_Empty(result);
BitVector_LSB(result, BitVector_Lexicompare(op1, op2) > 0);
break;
case YASM_EXPR_LE:
BitVector_Empty(result);
BitVector_LSB(result, BitVector_Lexicompare(op1, op2) <= 0);
break;
case YASM_EXPR_GE:
BitVector_Empty(result);
BitVector_LSB(result, BitVector_Lexicompare(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(line, N_("invalid use of '%s'"), "SEG");
break;
case YASM_EXPR_WRT:
yasm__error(line, N_("invalid use of '%s'"), "WRT");
break;
case YASM_EXPR_SEGOFF:
yasm__error(line, N_("invalid use of '%s'"), ":");
break;
case YASM_EXPR_IDENT:
if (result)
BitVector_Copy(result, op1);
break;
default:
yasm_internal_error(N_("invalid operation in intnum calculation"));
}
/* Try to fit the result into 32 bits if possible */
if (Set_Max(result) < 32) {
if (acc->type == INTNUM_BV) {
BitVector_Destroy(acc->val.bv);
acc->type = INTNUM_UL;
}
acc->val.ul = BitVector_Chunk_Read(result, 32, 0);
} else {
if (acc->type == INTNUM_BV) {
BitVector_Copy(acc->val.bv, result);
} else {
acc->type = INTNUM_BV;
acc->val.bv = BitVector_Clone(result);
}
}
}
/*@=nullderef =nullpass =branchstate@*/
void
yasm_intnum_zero(yasm_intnum *intn)
{
yasm_intnum_set_uint(intn, 0);
}
void
yasm_intnum_set_uint(yasm_intnum *intn, unsigned long val)
{
if (intn->type == INTNUM_BV) {
BitVector_Destroy(intn->val.bv);
intn->type = INTNUM_UL;
}
intn->val.ul = val;
}
int
yasm_intnum_is_zero(const yasm_intnum *intn)
{
return (intn->type == INTNUM_UL && intn->val.ul == 0);
}
int
yasm_intnum_is_pos1(const yasm_intnum *intn)
{
return (intn->type == INTNUM_UL && intn->val.ul == 1);
}
int
yasm_intnum_is_neg1(const yasm_intnum *intn)
{
return (intn->type == INTNUM_BV && BitVector_is_full(intn->val.bv));
}
int
yasm_intnum_sign(const yasm_intnum *intn)
{
if (intn->type == INTNUM_UL) {
if (intn->val.ul == 0)
return 0;
else
return 1;
} else
return BitVector_Sign(intn->val.bv);
}
unsigned long
yasm_intnum_get_uint(const yasm_intnum *intn)
{
switch (intn->type) {
case INTNUM_UL:
return intn->val.ul;
case INTNUM_BV:
return BitVector_Chunk_Read(intn->val.bv, 32, 0);
default:
yasm_internal_error(N_("unknown intnum type"));
/*@notreached@*/
return 0;
}
}
long
yasm_intnum_get_int(const yasm_intnum *intn)
{
switch (intn->type) {
case INTNUM_UL:
/* unsigned long values are always positive; max out if needed */
return (intn->val.ul & 0x80000000) ? LONG_MAX : (long)intn->val.ul;
case INTNUM_BV:
if (BitVector_msb_(intn->val.bv)) {
/* it's negative: negate the bitvector to get a positive
* number, then negate the positive number.
*/
unsigned long ul;
BitVector_Negate(conv_bv, intn->val.bv);
if (Set_Max(conv_bv) >= 32) {
/* too negative */
return LONG_MIN;
}
ul = BitVector_Chunk_Read(conv_bv, 32, 0);
/* check for too negative */
return (ul & 0x80000000) ? LONG_MIN : -((long)ul);
}
/* it's positive, and since it's a BV, it must be >0x7FFFFFFF */
return LONG_MAX;
default:
yasm_internal_error(N_("unknown intnum type"));
/*@notreached@*/
return 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, unsigned long line)
{
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__warning(YASM_WARN_GENERAL, line,
N_("value does not fit in signed %d bit field"),
valsize);
if (warn>0 && !yasm_intnum_check_size(intn, valsize, rshift, 2))
yasm__warning(YASM_WARN_GENERAL, line,
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, destsize);
/* If not already a bitvect, convert value to be written to a bitvect */
if (intn->type == INTNUM_BV)
op2 = intn->val.bv;
else {
op2 = op2static;
BitVector_Empty(op2);
BitVector_Chunk_Store(op2, 32, 0, intn->val.ul);
}
/* Check low bits if right shifting and warnings enabled */
if (warn && rshift > 0) {
BitVector_Copy(conv_bv, op2);
BitVector_Move_Left(conv_bv, BITVECT_NATIVE_SIZE-rshift);
if (!BitVector_is_empty(conv_bv))
yasm__warning(YASM_WARN_GENERAL, line,
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, 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);
}
/* 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 = conv_bv;
BitVector_Empty(val);
BitVector_Chunk_Store(val, 32, 0, intn->val.ul);
}
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);
}
static unsigned long
get_leb128(wordptr val, unsigned char *ptr, int sign)
{
unsigned long i, size;
unsigned char *ptr_orig = ptr;
if (sign) {
/* Signed mode */
if (BitVector_msb_(val)) {
/* Negative */
BitVector_Negate(conv_bv, val);
size = Set_Max(conv_bv)+2;
} else {
/* Positive */
size = Set_Max(val)+2;
}
} else {
/* Unsigned mode */
size = Set_Max(val)+1;
}
/* Positive/Unsigned write */
for (i=0; i<size; i += 7) {
*ptr = (unsigned char)BitVector_Chunk_Read(val, 7, i);
*ptr |= 0x80;
ptr++;
}
*(ptr-1) &= 0x7F; /* Clear MSB of last byte */
return (unsigned long)(ptr-ptr_orig);
}
static unsigned long
size_leb128(wordptr val, int sign)
{
if (sign) {
/* Signed mode */
if (BitVector_msb_(val)) {
/* Negative */
BitVector_Negate(conv_bv, val);
return (Set_Max(conv_bv)+8)/7;
} else {
/* Positive */
return (Set_Max(val)+8)/7;
}
} else {
/* Unsigned mode */
return (Set_Max(val)+7)/7;
}
}
unsigned long
yasm_intnum_get_leb128(const yasm_intnum *intn, unsigned char *ptr, int sign)
{
wordptr val = op1static;
/* Shortcut 0 */
if (intn->type == INTNUM_UL && intn->val.ul == 0) {
*ptr = 0;
return 1;
}
/* If not already a bitvect, convert value to be written to a bitvect */
if (intn->type == INTNUM_BV)
val = intn->val.bv;
else {
BitVector_Empty(val);
BitVector_Chunk_Store(val, 32, 0, intn->val.ul);
}
return get_leb128(val, ptr, sign);
}
unsigned long
yasm_intnum_size_leb128(const yasm_intnum *intn, int sign)
{
wordptr val = op1static;
/* Shortcut 0 */
if (intn->type == INTNUM_UL && intn->val.ul == 0) {
return 1;
}
/* If not already a bitvect, convert value to a bitvect */
if (intn->type == INTNUM_BV)
val = intn->val.bv;
else {
BitVector_Empty(val);
BitVector_Chunk_Store(val, 32, 0, intn->val.ul);
}
return size_leb128(val, sign);
}
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_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_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);
}
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);
}
void
yasm_intnum_print(const yasm_intnum *intn, FILE *f)
{
unsigned char *s;
switch (intn->type) {
case INTNUM_UL:
fprintf(f, "0x%lx/%u", intn->val.ul, (unsigned int)intn->origsize);
break;
case INTNUM_BV:
s = BitVector_to_Hex(intn->val.bv);
fprintf(f, "0x%s/%u", (char *)s, (unsigned int)intn->origsize);
yasm_xfree(s);
break;
}
}