From 91ac655c47a775f51bd153d0842147bbd3fcdfc1 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Thu, 9 Feb 2006 05:00:09 +0000 Subject: [PATCH] * intnum.h (yasm_get_sleb128, yasm_size_sleb128): New functions to handle signed LEB128-encoded numbers straight from long values (rather than going through intnum). (yasm_get_uleb128, yasm_size_uleb128): Likewise, for unsigned LEB128. * intnum.c (get_leb128, size_leb128): Move most of functionality here from: (yasm_intnum_get_leb128, yasm_intnum_size_leb128): Here (refactor). (yasm_get_sleb128, yasm_size_sleb128, yasm_get_uleb128, yasm_size_uleb128): Implement using refactored functionality. svn path=/trunk/yasm/; revision=1366 --- libyasm/intnum.c | 141 +++++++++++++++++++++++++++++++++++++---------- libyasm/intnum.h | 26 +++++++++ 2 files changed, 137 insertions(+), 30 deletions(-) diff --git a/libyasm/intnum.c b/libyasm/intnum.c index 6544a86d..6329f41e 100644 --- a/libyasm/intnum.c +++ b/libyasm/intnum.c @@ -656,27 +656,12 @@ yasm_intnum_check_size(const yasm_intnum *intn, size_t size, size_t rshift, return (Set_Max(val) < (long)size); } -unsigned long -yasm_intnum_get_leb128(const yasm_intnum *intn, unsigned char *ptr, int sign) +static unsigned long +get_leb128(wordptr val, unsigned char *ptr, int sign) { - wordptr val = op1static; unsigned long i, size; unsigned char *ptr_orig = ptr; - /* 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); - } - if (sign) { /* Signed mode */ if (BitVector_msb_(val)) { @@ -702,6 +687,47 @@ yasm_intnum_get_leb128(const yasm_intnum *intn, unsigned char *ptr, int sign) 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) { @@ -720,20 +746,75 @@ yasm_intnum_size_leb128(const yasm_intnum *intn, int sign) BitVector_Chunk_Store(val, 32, 0, intn->val.ul); } - 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; + 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 diff --git a/libyasm/intnum.h b/libyasm/intnum.h index 645047e3..e05ac1c8 100644 --- a/libyasm/intnum.h +++ b/libyasm/intnum.h @@ -214,6 +214,32 @@ unsigned long yasm_intnum_get_leb128(const yasm_intnum *intn, */ unsigned long yasm_intnum_size_leb128(const yasm_intnum *intn, int sign); +/** Output integer to buffer in signed LEB128-encoded form. + * \param v integer + * \param ptr pointer to storage for output bytes + * \return Number of bytes generated. + */ +unsigned long yasm_get_sleb128(long v, unsigned char *ptr); + +/** Calculate number of bytes signed LEB128-encoded form of integer will take. + * \param v integer + * \return Number of bytes. + */ +unsigned long yasm_size_sleb128(long v); + +/** Output integer to buffer in unsigned LEB128-encoded form. + * \param v integer + * \param ptr pointer to storage for output bytes + * \return Number of bytes generated. + */ +unsigned long yasm_get_uleb128(unsigned long v, unsigned char *ptr); + +/** Calculate number of bytes unsigned LEB128-encoded form of integer will take. + * \param v integer + * \return Number of bytes. + */ +unsigned long yasm_size_uleb128(unsigned long v); + /** Print an intnum. For debugging purposes. * \param f file * \param intn intnum