]> granicus.if.org Git - yasm/commitdiff
Big output_expr(), intnum_tobytes(), and floatnum_tobytes() changes:
authorPeter Johnson <peter@tortall.net>
Fri, 25 Jul 2003 03:27:21 +0000 (03:27 -0000)
committerPeter Johnson <peter@tortall.net>
Fri, 25 Jul 2003 03:27:21 +0000 (03:27 -0000)
 - Switch to bit-based output, including shift capability
 - This means the standard intnum output functions can be used for non-byte
   oriented archs like LC-3b (implemented)
 - Default out of range (overflow) warnings for intnum (bugzilla bug 14)
 - Change floating point overflow/underflow errors to warnings
To do (hooks but not implemented):
 - Shifting floatnums into destination
 - Floatnum destinations larger than floatnum value
 - Big endian support for intnum and floatnum
Related simultaneous changes:
 - Use bc instead of ep in objfmt output_expr() functions; while bc->line
   should == (*ep)->line, in case they differ, we want to use the bc->line
   so as not to confuse users.
 - lc3b-mp22NC test was not properly offsetting the accessed variables, but
   since the variable "sections" started at an aligned offset, the output
   was actually correct.  The new intnum warnings uncovered this issue, so
   fix code to be correct (and not generate warnings).

svn path=/trunk/yasm/; revision=1017

25 files changed:
libyasm/arch.h
libyasm/bytecode.c
libyasm/coretype.h
libyasm/floatnum.c
libyasm/floatnum.h
libyasm/intnum.c
libyasm/intnum.h
libyasm/tests/floatnum_test.c
modules/arch/lc3b/lc3barch.c
modules/arch/lc3b/lc3barch.h
modules/arch/lc3b/lc3bbc.c
modules/arch/lc3b/tests/lc3b-mp22NC.asm
modules/arch/x86/tests/Makefile.inc
modules/arch/x86/tests/overflow.asm [new file with mode: 0644]
modules/arch/x86/tests/overflow.errwarn [new file with mode: 0644]
modules/arch/x86/tests/overflow.hex [new file with mode: 0644]
modules/arch/x86/tests/twobytemem.errwarn
modules/arch/x86/x86arch.h
modules/arch/x86/x86bc.c
modules/arch/x86/x86expr.c
modules/objfmts/bin/bin-objfmt.c
modules/objfmts/bin/tests/float-err.errwarn
modules/objfmts/bin/tests/integer-warn.errwarn
modules/objfmts/coff/coff-objfmt.c
modules/objfmts/elf/elf-objfmt.c

index eacdce57c58f9bdf43319401dd4227c2618ba47b..2142d5b8e66a38698f8c731ffc0599efac980fe0 100644 (file)
@@ -215,31 +215,45 @@ struct yasm_arch {
                       const yasm_section *sect, void *d,
                       yasm_output_expr_func output_expr);
 
-    /** Output #yasm_floatnum to buffer.
+    /** Output #yasm_floatnum to buffer.  Puts the value into the least
+     * significant bits of the destination, or may be shifted into more
+     * significant bits by the shift parameter.  The destination bits are
+     * cleared before being set.
      * Architecture-specific because of endianness.
      * \param flt      floating point value
-     * \param bufp     buffer to write into
-     * \param valsize  length (in bytes)
-     * \param e                expression containing value
-     * \return Nonzero on error, otherwise updates *bufp by valsize (number of
-     * bytes saved to bufp).
+     * \param buf      buffer to write into
+     * \param destsize destination size (in bytes)
+     * \param valsize  size (in bits)
+     * \param shift    left shift (in bits)
+     * \param warn     enables standard overflow/underflow warnings
+     * \param lindex   line index; may be 0 if warn is 0.
+     * \return Nonzero on error.
      */
-    int (*floatnum_tobytes) (const yasm_floatnum *flt, unsigned char **bufp,
-                            unsigned long valsize, const yasm_expr *e);
-
-    /** Output #yasm_intnum to buffer.
+    int (*floatnum_tobytes) (const yasm_floatnum *flt, unsigned char *buf,
+                            size_t destsize, size_t valsize, size_t shift,
+                            int warn, unsigned long lindex);
+
+    /** Output #yasm_intnum to buffer.  Puts the value into the least
+     * significant bits of the destination, or may be shifted into more
+     * significant bits by the shift parameter.  The destination bits are
+     * cleared before being set.
      * \param intn     integer value
-     * \param bufp     buffer to write into
-     * \param valsize  length (in bytes)
-     * \param e                expression containing value
+     * \param buf      buffer to write into
+     * \param destsize destination size (in bytes)
+     * \param valsize  size (in bits)
+     * \param shift    left shift (in bits); may be negative to specify right
+     *                 shift (standard warnings include truncation to boundary)
      * \param bc       bytecode being output ("parent" of value)
      * \param rel      value is a relative displacement from bc
-     * \return Nonzero on error, otherwise updates *bufp by valsize (number of
-     * bytes saved to bufp).
+     * \param warn     enables standard warnings (value doesn't fit into
+     *                 valsize bits)
+     * \param lindex   line index; may be 0 if warn is 0
+     * \return Nonzero on error.
      */
-    int (*intnum_tobytes) (const yasm_intnum *intn, unsigned char **bufp,
-                          unsigned long valsize, const yasm_expr *e,
-                          const yasm_bytecode *bc, int rel);
+    int (*intnum_tobytes) (const yasm_intnum *intn, unsigned char *buf,
+                          size_t destsize, size_t valsize, int shift,
+                          const yasm_bytecode *bc, int rel, int warn,
+                          unsigned long lindex);
 
     /** Get the equivalent byte size of a register.
      * \param reg      register
index 14ae8ec97555a445fd42166cacea10f2c72196d1..f26059fe87a2eaa97c2c73a2095aadf52a12adba 100644 (file)
@@ -690,10 +690,12 @@ bc_tobytes_data(bytecode_data *bc_data, unsigned char **bufp,
            case DV_EMPTY:
                break;
            case DV_EXPR:
-               if (output_expr(&dv->data.expn, bufp, bc_data->size,
+               if (output_expr(&dv->data.expn, *bufp, bc_data->size,
+                               bc_data->size*8, 0,
                                (unsigned long)(*bufp-bufp_orig), sect, bc, 0,
-                               d))
+                               1, d))
                    return 1;
+               *bufp += bc_data->size;
                break;
            case DV_STRING:
                slen = strlen(dv->data.str_val);
index 6a4dad86022f30452f11d0652d1aabb4d9f2ce54..46d8762da48cb12f82b3dabe7f755b2ce125c13f 100644 (file)
@@ -147,9 +147,15 @@ typedef /*@null@*/ yasm_intnum * (*yasm_calc_bc_dist_func)
 
 /** Convert yasm_expr to its byte representation.  Usually implemented by
  * object formats to keep track of relocations and verify legal expressions.
+ * Must put the value into the least significant bits of the destination,
+ * unless shifted into more significant bits by the shift parameter.  The
+ * destination bits must be cleared before being set.
  * \param ep           (double) pointer to expression
- * \param bufp         (double) pointer to buffer for byte representation
- * \param valsize      size (in bytes) of the byte representation
+ * \param buf          buffer for byte representation
+ * \param destsize     destination size (in bytes)
+ * \param valsize      size (in bits)
+ * \param shift                left shift (in bits); may be negative to specify right
+ *                     shift (standard warnings include truncation to boundary)
  * \param offset       offset (in bytes) of the expr contents from the start
  *                     of the bytecode (sometimes needed for conditional jumps)
  * \param sect         current section (usually passed into higher-level
@@ -157,15 +163,19 @@ typedef /*@null@*/ yasm_intnum * (*yasm_calc_bc_dist_func)
  * \param bc           current bytecode (usually passed into higher-level
  *                     calling function)
  * \param rel          if nonzero, expr should be treated as PC/IP-relative
+ * \param warn         enables standard warnings: zero for none;
+ *                     nonzero for overflow/underflow floating point warnings;
+ *                     negative for signed integer warnings,
+ *                     positive for unsigned integer warnings
  * \param d            objfmt-specific data (passed into higher-level calling
  *                     function)
  * \return Nonzero if an error occurred, 0 otherwise.
  */
 typedef int (*yasm_output_expr_func)
-    (yasm_expr **ep, unsigned char **bufp, unsigned long valsize,
-     unsigned long offset, /*@observer@*/ const yasm_section *sect,
-     yasm_bytecode *bc, int rel, /*@null@*/ void *d)
-    /*@uses *ep@*/ /*@sets **bufp@*/;
+    (yasm_expr **ep, /*@out@*/ unsigned char *buf, size_t destsize,
+     size_t valsize, int shift, unsigned long offset,
+     /*@observer@*/ const yasm_section *sect, yasm_bytecode *bc, int rel,
+     int warn, /*@null@*/ void *d) /*@uses *ep@*/;
 
 /** Convert a yasm_objfmt-specific data bytecode into its byte representation.
  * Usually implemented by object formats to output their own generated data.
index 11fc3863dddb267239933656dfd80c5d6e6e9e60..e9addc28e74914e9e27429bd123bbdf65427e0a8 100644 (file)
@@ -525,7 +525,7 @@ yasm_floatnum_get_int(const yasm_floatnum *flt, unsigned long *ret_val)
 {
     unsigned char t[4];
 
-    if (yasm_floatnum_get_sized(flt, t, 4)) {
+    if (yasm_floatnum_get_sized(flt, t, 4, 32, 0, 0, 0, 0)) {
        *ret_val = 0xDEADBEEFUL;    /* Obviously incorrect return value */
        return 1;
     }
@@ -659,20 +659,38 @@ floatnum_get_common(const yasm_floatnum *flt, /*@out@*/ unsigned char *ptr,
  */
 int
 yasm_floatnum_get_sized(const yasm_floatnum *flt, unsigned char *ptr,
-                       size_t size)
+                       size_t destsize, size_t valsize, size_t shift,
+                       int bigendian, int warn, unsigned long lindex)
 {
-    switch (size) {
+    int retval;
+    if (destsize*8 != valsize || shift>0 || bigendian) {
+       /* TODO */
+       yasm_internal_error(N_("unsupported floatnum functionality"));
+    }
+    switch (destsize) {
        case 4:
-           return floatnum_get_common(flt, ptr, 4, 23, 1, 8);
+           retval = floatnum_get_common(flt, ptr, 4, 23, 1, 8);
+           break;
        case 8:
-           return floatnum_get_common(flt, ptr, 8, 52, 1, 11);
+           retval = floatnum_get_common(flt, ptr, 8, 52, 1, 11);
+           break;
        case 10:
-           return floatnum_get_common(flt, ptr, 10, 64, 0, 15);
+           retval = floatnum_get_common(flt, ptr, 10, 64, 0, 15);
+           break;
        default:
            yasm_internal_error(N_("Invalid float conversion size"));
            /*@notreached@*/
-           return 1;       /* never reached, but silence GCC warning */
+           return 1;
+    }
+    if (warn) {
+       if (retval < 0)
+           yasm__warning(YASM_WARN_GENERAL, lindex,
+                         N_("underflow in floating point expression"));
+       else if (retval > 0)
+           yasm__warning(YASM_WARN_GENERAL, lindex,
+                         N_("overflow in floating point expression"));
     }
+    return retval;
 }
 
 /* 1 if the size is valid, 0 if it isn't */
@@ -680,9 +698,9 @@ int
 yasm_floatnum_check_size(/*@unused@*/ const yasm_floatnum *flt, size_t size)
 {
     switch (size) {
-       case 4:
-       case 8:
-       case 10:
+       case 32:
+       case 64:
+       case 80:
            return 1;
        default:
            return 0;
@@ -703,19 +721,22 @@ yasm_floatnum_print(FILE *f, const yasm_floatnum *flt)
     yasm_xfree(str);
 
     /* 32-bit (single precision) format */
-    fprintf(f, "32-bit: %d: ", yasm_floatnum_get_sized(flt, out, 4));
+    fprintf(f, "32-bit: %d: ",
+           yasm_floatnum_get_sized(flt, out, 4, 32, 0, 0, 0, 0));
     for (i=0; i<4; i++)
        fprintf(f, "%02x ", out[i]);
     fprintf(f, "\n");
 
     /* 64-bit (double precision) format */
-    fprintf(f, "64-bit: %d: ", yasm_floatnum_get_sized(flt, out, 8));
+    fprintf(f, "64-bit: %d: ",
+           yasm_floatnum_get_sized(flt, out, 8, 64, 0, 0, 0, 0));
     for (i=0; i<8; i++)
        fprintf(f, "%02x ", out[i]);
     fprintf(f, "\n");
 
     /* 80-bit (extended precision) format */
-    fprintf(f, "80-bit: %d: ", yasm_floatnum_get_sized(flt, out, 10));
+    fprintf(f, "80-bit: %d: ",
+           yasm_floatnum_get_sized(flt, out, 10, 80, 0, 0, 0, 0));
     for (i=0; i<10; i++)
        fprintf(f, "%02x ", out[i]);
     fprintf(f, "\n");
index 4d2f17219f0b80593ff2f90ad2b68b1a63290da6..98b5cbaae834a3c97028c6954d3ab2674d23e384 100644 (file)
@@ -81,26 +81,34 @@ void yasm_floatnum_calc(yasm_floatnum *acc, yasm_expr_op op,
 int yasm_floatnum_get_int(const yasm_floatnum *flt,
                          /*@out@*/ unsigned long *ret_val);
 
-/** Convert a floatnum to Intel-format little-endian byte string.
- * [0] should be the first byte output to an Intel-format file.
- * \note Not all sizes are valid.  Currently, only 4 (single-precision), 8
- *       (double-precision), and 10 (extended-precision) are valid sizes.
+/** Output a #yasm_floatnum to buffer in little-endian or big-endian.  Puts the
+ * value into the least significant bits of the destination, or may be shifted
+ * into more significant bits by the shift parameter.  The destination bits are
+ * cleared before being set.  [0] should be the first byte output to the file.
+ * \note Not all sizes are valid.  Currently, only 32 (single-precision), 64
+ *       (double-precision), and 80 (extended-precision) are valid sizes.
  *       Use yasm_floatnum_check_size() to check for supported sizes.
  * \param flt      floatnum
  * \param ptr      pointer to storage for size bytes of output
- * \param size     size (in bytes) of desired output.
+ * \param destsize  destination size (in bytes)
+ * \param valsize   size (in bits)
+ * \param shift            left shift (in bits)
+ * \param bigendian endianness (nonzero=big, zero=little)
+ * \param warn     enables standard overflow/underflow warnings
+ * \param lindex    line index; may be 0 if warn is 0.
  * \return Nonzero if flt can't fit into the specified precision: -1 if
  *         underflow occurred, 1 if overflow occurred.
  */
-int yasm_floatnum_get_sized(const yasm_floatnum *flt,
-                           /*@out@*/ unsigned char *ptr, size_t size);
+int yasm_floatnum_get_sized(const yasm_floatnum *flt, unsigned char *ptr,
+                           size_t destsize, size_t valsize, size_t shift,
+                           int bigendian, int warn, unsigned long lindex);
 
 /** Basic check to see if size is valid for flt conversion (using
  * yasm_floatnum_get_sized()).  Doesn't actually check for underflow/overflow
- * but rather checks for size=4,8,10
+ * but rather checks for size=32,64,80
  * (at present).
  * \param flt      floatnum
- * \param size     size (in bytes) of desired conversion output
+ * \param size     number of bits of output space
  * \return 1 if valid size, 0 if invalid size.
  */
 int yasm_floatnum_check_size(const yasm_floatnum *flt, size_t size);
index 28525fcd58c7a64496a7e9c3b3c8328b33c34c9c..6a3db21cf5d8af8afaca024a369443fc553a92b0 100644 (file)
@@ -488,17 +488,14 @@ yasm_intnum_get_int(const yasm_intnum *intn)
                /* it's negative: negate the bitvector to get a positive
                 * number, then negate the positive number.
                 */
-               wordptr abs_bv = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
                unsigned long ul;
 
-               BitVector_Negate(abs_bv, intn->val.bv);
-               if (Set_Max(abs_bv) >= 32) {
+               BitVector_Negate(conv_bv, intn->val.bv);
+               if (Set_Max(conv_bv) >= 32) {
                    /* too negative */
-                   BitVector_Destroy(abs_bv);
                    return LONG_MIN;
                }
-               ul = BitVector_Chunk_Read(abs_bv, 32, 0);
-               BitVector_Destroy(abs_bv);
+               ul = BitVector_Chunk_Read(conv_bv, 32, 0);
                /* check for too negative */
                return (ul & 0x80000000) ? LONG_MIN : -((long)ul);
            }
@@ -513,92 +510,116 @@ yasm_intnum_get_int(const yasm_intnum *intn)
 }
 
 void
-yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr, size_t size)
+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 lindex)
 {
-    unsigned long ul;
+    wordptr op1 = op1static, op2;
     unsigned char *buf;
     unsigned int len;
+    size_t rshift = shift < 0 ? (size_t)(-shift) : 0;
+    int carry_in;
 
-    switch (intn->type) {
-       case INTNUM_UL:
-           ul = intn->val.ul;
-           while (size-- > 0) {
-               YASM_WRITE_8(ptr, ul);
-               if (ul != 0)
-                   ul >>= 8;
-           }
-           break;
-       case INTNUM_BV:
-           buf = BitVector_Block_Read(intn->val.bv, &len);
-           if (len < (unsigned int)size)
-               yasm_internal_error(N_("Invalid size specified (too large)"));
-           memcpy(ptr, buf, size);
-           yasm_xfree(buf);
-           break;
+    /* 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 && !yasm_intnum_check_size(intn, valsize, rshift, 2))
+       yasm__warning(YASM_WARN_GENERAL, lindex,
+                     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, lindex,
+                         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, 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, int is_signed)
+yasm_intnum_check_size(const yasm_intnum *intn, size_t size, size_t rshift,
+                      int rangetype)
 {
-    if (is_signed) {
-       switch (intn->type) {
-           case INTNUM_UL:
-               if (size >= 4)
-                   return 1;
-
-               /* INTNUM_UL is always positive */
-               switch (size) {
-                   case 4:
-                       return (intn->val.ul <= 0x7FFFFFFF);
-                   case 3:
-                       return (intn->val.ul <= 0x007FFFFF);
-                   case 2:
-                       return (intn->val.ul <= 0x00007FFF);
-                   case 1:
-                       return (intn->val.ul <= 0x0000007F);
-               }
-               break;
-           case INTNUM_BV:
-               if (size >= BITVECT_NATIVE_SIZE/8)
-                   return 1;
-               if (BitVector_msb_(intn->val.bv)) {
-                   /* it's negative */
-                   wordptr abs_bv = BitVector_Create(BITVECT_NATIVE_SIZE,
-                                                     FALSE);
-                   int retval;
-
-                   BitVector_Negate(abs_bv, intn->val.bv);
-                   retval = Set_Max(abs_bv) < (long)(size*8);
-
-                   BitVector_Destroy(abs_bv);
-                   return retval;
-               } else
-                   return (Set_Max(intn->val.bv) < (long)(size*8));
-       }
+    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 {
-       switch (intn->type) {
-           case INTNUM_UL:
-               if (size >= 4)
-                   return 1;
-               switch (size) {
-                   case 3:
-                       return ((intn->val.ul & 0x00FFFFFF) == intn->val.ul);
-                   case 2:
-                       return ((intn->val.ul & 0x0000FFFF) == intn->val.ul);
-                   case 1:
-                       return ((intn->val.ul & 0x000000FF) == intn->val.ul);
-               }
-               break;
-           case INTNUM_BV:
-               if (size >= BITVECT_NATIVE_SIZE/8)
-                   return 1;
-               else
-                   return (Set_Max(intn->val.bv) < (long)(size*8));
+       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 0;
+    return (Set_Max(val) < (long)size);
 }
 
 void
index 737a4016e810494e10f3af2a3af6cb88e711e3a9..b6d8350069f59ad153ef7049013931b3ae0d5682 100644 (file)
@@ -148,26 +148,38 @@ unsigned long yasm_intnum_get_uint(const yasm_intnum *intn);
  */
 long yasm_intnum_get_int(const yasm_intnum *intn);
 
-/** Convert an intnum to Intel-format little-endian byte string.
- * [0] should be the first byte output to an Intel-format file.
- * \note Parameter intnum is truncated to fit into specified size.  Use
- *       intnum_check_size() to check for overflow.
+/** Output #yasm_intnum to buffer in little-endian or big-endian.  Puts the
+ * value into the least significant bits of the destination, or may be shifted
+ * into more significant bits by the shift parameter.  The destination bits are
+ * cleared before being set.  [0] should be the first byte output to the file.
  * \param intn     intnum
  * \param ptr      pointer to storage for size bytes of output
- * \param size     size (in bytes) of desired output.
+ * \param destsize  destination size (in bytes)
+ * \param valsize   size (in bits)
+ * \param shift            left shift (in bits); may be negative to specify right
+ *                 shift (standard warnings include truncation to boundary)
+ * \param bigendian endianness (nonzero=big, zero=little)
+ * \param warn     enables standard warnings (value doesn't fit into valsize
+ *                 bits)
+ * \param lindex    line index; may be 0 if warn is 0
  */
 void yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr,
-                          size_t size);
+                          size_t destsize, size_t valsize, int shift,
+                          int bigendian, int warn, unsigned long lindex);
 
-/** Check to see if intnum will fit without overflow into size bytes.
+/** Check to see if intnum will fit without overflow into size bits.
  * If is_signed is 1, intnum is treated as a signed number.
  * \param intn     intnum
- * \param size     number of bytes of output space
- * \param is_signed nonzero, intnum should be treated as signed
+ * \param size     number of bits of output space
+ * \param rshift    right shift
+ * \param rangetype signed/unsigned range selection:
+ *                 0 => (0, unsigned max);
+ *                 1 => (signed min, signed max);
+ *                 2 => (signed min, unsigned max)
  * \return Nonzero if intnum will fit.
  */
 int yasm_intnum_check_size(const yasm_intnum *intn, size_t size,
-                          int is_signed);
+                          size_t rshift, int rangetype);
 
 /** Print an intnum.  For debugging purposes.
  * \param f    file
index 41875b14bbc65b5a554301f430417ab22055dde2..c3e2eec38d7b953173d244671c8fab1fdc50ee82 100644 (file)
@@ -292,8 +292,8 @@ START_TEST(test_get_single_normalized)
 
     for (i=0; i<num; i++) {
        get_common_setup(vals, i);
-       fail_unless(yasm_floatnum_get_sized(flt, outval, 4) == vals[i].ret32,
-                   ret_msg);
+       fail_unless(yasm_floatnum_get_sized(flt, outval, 4, 32, 0, 0, 0, 0) ==
+                   vals[i].ret32, ret_msg);
        fail_unless(get_common_check_result(4, outval, vals[i].result32) == 0,
                    result_msg);
     }
@@ -308,8 +308,8 @@ START_TEST(test_get_single_normalized_edgecase)
 
     for (i=0; i<num; i++) {
        get_common_setup(vals, i);
-       fail_unless(yasm_floatnum_get_sized(flt, outval, 4) == vals[i].ret32,
-                   ret_msg);
+       fail_unless(yasm_floatnum_get_sized(flt, outval, 4, 32, 0, 0, 0, 0) ==
+                   vals[i].ret32, ret_msg);
        fail_unless(get_common_check_result(4, outval, vals[i].result32) == 0,
                    result_msg);
     }
@@ -328,8 +328,8 @@ START_TEST(test_get_double_normalized)
 
     for (i=0; i<num; i++) {
        get_common_setup(vals, i);
-       fail_unless(yasm_floatnum_get_sized(flt, outval, 8) == vals[i].ret64,
-                   ret_msg);
+       fail_unless(yasm_floatnum_get_sized(flt, outval, 8, 64, 0, 0, 0, 0) ==
+                   vals[i].ret64, ret_msg);
        fail_unless(get_common_check_result(8, outval, vals[i].result64) == 0,
                    result_msg);
     }
@@ -344,8 +344,8 @@ START_TEST(test_get_double_normalized_edgecase)
 
     for (i=0; i<num; i++) {
        get_common_setup(vals, i);
-       fail_unless(yasm_floatnum_get_sized(flt, outval, 8) == vals[i].ret64,
-                   ret_msg);
+       fail_unless(yasm_floatnum_get_sized(flt, outval, 8, 64, 0, 0, 0, 0) ==
+                   vals[i].ret64, ret_msg);
        fail_unless(get_common_check_result(8, outval, vals[i].result64) == 0,
                    result_msg);
     }
@@ -364,8 +364,8 @@ START_TEST(test_get_extended_normalized)
 
     for (i=0; i<num; i++) {
        get_common_setup(vals, i);
-       fail_unless(yasm_floatnum_get_sized(flt, outval, 10) == vals[i].ret80,
-                   ret_msg);
+       fail_unless(yasm_floatnum_get_sized(flt, outval, 10, 80, 0, 0, 0, 0) ==
+                   vals[i].ret80, ret_msg);
        fail_unless(get_common_check_result(10, outval, vals[i].result80) == 0,
                    result_msg);
     }
@@ -380,8 +380,8 @@ START_TEST(test_get_extended_normalized_edgecase)
 
     for (i=0; i<num; i++) {
        get_common_setup(vals, i);
-       fail_unless(yasm_floatnum_get_sized(flt, outval, 10) == vals[i].ret80,
-                   ret_msg);
+       fail_unless(yasm_floatnum_get_sized(flt, outval, 10, 80, 0, 0, 0, 0) ==
+                   vals[i].ret80, ret_msg);
        fail_unless(get_common_check_result(10, outval, vals[i].result80) == 0,
                    result_msg);
     }
index 8606d529775b5adcb4db44f65d861cbcf7ab0984..a795889b47c71705617408169eabfea19f7114d5 100644 (file)
@@ -28,7 +28,6 @@
 /*@unused@*/ RCSID("$IdPath$");
 
 #define YASM_LIB_INTERNAL
-#define YASM_EXPR_INTERNAL
 #include <libyasm.h>
 
 #include "lc3barch.h"
@@ -68,10 +67,11 @@ yasm_lc3b__reg_print(FILE *f, unsigned long reg)
 }
 
 static int
-yasm_lc3b__floatnum_tobytes(const yasm_floatnum *flt, unsigned char **bufp,
-                           unsigned long valsize, const yasm_expr *e)
+yasm_lc3b__floatnum_tobytes(const yasm_floatnum *flt, unsigned char *buf,
+                           size_t destsize, size_t valsize, size_t shift,
+                           int warn, unsigned long lindex)
 {
-    yasm__error(e->line, N_("LC-3b does not support floating point"));
+    yasm__error(lindex, N_("LC-3b does not support floating point"));
     return 1;
 }
 
index 70071bb838dcef26e7cd7f055df528e46a5f1aec..72164106784d33084dc71458e8778879a544178b 100644 (file)
@@ -81,9 +81,10 @@ int yasm_lc3b__parse_directive(const char *name, yasm_valparamhead *valparams,
      /*@null@*/ yasm_insn_operandhead *operands, yasm_section *cur_section,
      /*@null@*/ yasm_bytecode *prev_bc, unsigned long lindex);
 
-int yasm_lc3b__intnum_tobytes(const yasm_intnum *intn, unsigned char **bufp,
-                             unsigned long valsize, const yasm_expr *e,
-                             const yasm_bytecode *bc, int rel);
+int yasm_lc3b__intnum_tobytes(const yasm_intnum *intn, unsigned char *buf,
+                             size_t destsize, size_t valsize, int shift,
+                             const yasm_bytecode *bc, int rel, int warn,
+                             unsigned long lindex);
 
 unsigned int yasm_lc3b__get_reg_size(unsigned long reg);
 
index aebacb3acd00a11c821e41e5f5ae4432b652275c..990632f89109899b81da5418c839ff641b6ed86f 100644 (file)
@@ -126,7 +126,7 @@ yasm_lc3b__bc_print(FILE *f, int indent_level, const yasm_bytecode *bc)
        }
        indent_level--;
     }
-    fprintf(f, "%*sOrigin=", indent_level, "");
+    fprintf(f, "\n%*sOrigin=", indent_level, "");
     if (insn->origin) {
        fprintf(f, "\n");
        yasm_symrec_print(f, indent_level+1, insn->origin);
@@ -172,7 +172,7 @@ yasm_lc3b__bc_resolve(yasm_bytecode *bc, int save, const yasm_section *sect,
     rel -= 2;
     yasm_expr_delete(temp);
     /* 9-bit signed, word-multiple displacement */
-    if (rel < -512 || rel > 512) {
+    if (rel < -512 || rel > 511) {
        yasm__error(bc->line, N_("target out of range"));
        return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
     }
@@ -185,86 +185,79 @@ yasm_lc3b__bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
                      yasm_output_expr_func output_expr)
 {
     lc3b_insn *insn;
-    unsigned int opcode;
-    unsigned int val;
-    int rel = 0;
 
     if ((lc3b_bytecode_type)bc->type != LC3B_BC_INSN)
        return 0;
 
     insn = (lc3b_insn *)bc;
 
-    /* Change into PC-relative if necessary */
-    if (insn->imm_type == LC3B_IMM_9_PC) {
-       insn->imm = yasm_expr_new(YASM_EXPR_SUB, yasm_expr_expr(insn->imm),
-                                 yasm_expr_sym(insn->origin), bc->line);
-       rel = 1;
-    }
-
-    /* Get immediate value */
-    if (output_expr(&insn->imm, bufp, 2, 0, sect, bc, rel, d))
-       return 1;
-    *bufp -= 2;
-    YASM_LOAD_16_L(val, *bufp);
+    /* Output opcode */
+    YASM_SAVE_16_L(*bufp, insn->opcode);
 
-    opcode = insn->opcode;
-
-    /* Insert immediate into opcode.  Warn on overflow? */
+    /* Insert immediate into opcode. */
     switch (insn->imm_type) {
        case LC3B_IMM_NONE:
            break;
        case LC3B_IMM_4:
-           opcode &= ~0xF;
-           opcode |= (val & 0xF);
+           if (output_expr(&insn->imm, *bufp, 2, 4, 0, 0, sect, bc, 0, 1, d))
+               return 1;
            break;
        case LC3B_IMM_5:
-           opcode &= ~0x1F;
-           opcode |= (val & 0x1F);
+           if (output_expr(&insn->imm, *bufp, 2, 5, 0, 0, sect, bc, 0, 1, d))
+               return 1;
            break;
        case LC3B_IMM_6_WORD:
-           if (val & 1)
-               yasm__warning(YASM_WARN_GENERAL, bc->line,
-                             N_("Misaligned access, truncating to boundary"));
-           val >>= 1;
-           /*@fallthrough@*/
+           if (output_expr(&insn->imm, *bufp, 2, 6, -1, 0, sect, bc, 0, 1, d))
+               return 1;
+           break;
        case LC3B_IMM_6_BYTE:
-           opcode &= ~0x3F;
-           opcode |= (val & 0x3F);
+           if (output_expr(&insn->imm, *bufp, 2, 6, 0, 0, sect, bc, 0, 1, d))
+               return 1;
            break;
        case LC3B_IMM_8:
-           if (val & 1)
-               yasm__warning(YASM_WARN_GENERAL, bc->line,
-                             N_("Misaligned access, truncating to boundary"));
-           opcode &= ~0xFF;
-           opcode |= ((val>>1) & 0xFF);
+           if (output_expr(&insn->imm, *bufp, 2, 8, -1, 0, sect, bc, 0, 1, d))
+               return 1;
            break;
        case LC3B_IMM_9_PC:
-           val -= 2;
-           /*@fallthrough@*/
+           insn->imm = yasm_expr_new(YASM_EXPR_SUB, yasm_expr_expr(insn->imm),
+                                     yasm_expr_sym(insn->origin), bc->line);
+           if (output_expr(&insn->imm, *bufp, 2, 9, -1, 0, sect, bc, 1, 1, d))
+               return 1;
+           break;
        case LC3B_IMM_9:
-           if (val & 1)
-               yasm__warning(YASM_WARN_GENERAL, bc->line,
-                             N_("Misaligned access, truncating to boundary"));
-           opcode &= ~0x1FF;
-           opcode |= ((val>>1) & 0x1FF);
+           if (output_expr(&insn->imm, *bufp, 2, 9, -1, 0, sect, bc, 0, 1, d))
+               return 1;
            break;
        default:
            yasm_internal_error(N_("Unrecognized immediate type"));
     }
 
-    /* Output it */
-    YASM_WRITE_16_L(*bufp, opcode);
-
+    *bufp += 2;            /* all instructions are 2 bytes in size */
     return 0;
 }
 
 int
-yasm_lc3b__intnum_tobytes(const yasm_intnum *intn, unsigned char **bufp,
-                         unsigned long valsize, const yasm_expr *e,
-                         const yasm_bytecode *bc, int rel)
+yasm_lc3b__intnum_tobytes(const yasm_intnum *intn, unsigned char *buf,
+                         size_t destsize, size_t valsize, int shift,
+                         const yasm_bytecode *bc, int rel, int warn,
+                         unsigned long lindex)
 {
-    /* Write value out. */
-    yasm_intnum_get_sized(intn, *bufp, (size_t)valsize);
-    *bufp += valsize;
+    if (rel) {
+       yasm_intnum *relnum, *delta;
+       if (valsize != 9)
+           yasm_internal_error(
+               N_("tried to do PC-relative offset from invalid sized value"));
+       relnum = yasm_intnum_copy(intn);
+       delta = yasm_intnum_new_uint(bc->len);
+       yasm_intnum_calc(relnum, YASM_EXPR_SUB, delta, lindex);
+       yasm_intnum_delete(delta);
+       yasm_intnum_get_sized(relnum, buf, destsize, valsize, shift, 0, warn,
+                             lindex);
+       yasm_intnum_delete(relnum);
+    } else {
+       /* Write value out. */
+       yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn,
+                             lindex);
+    }
     return 0;
 }
index be62d3b06ca2472e17a1cabf24d98759725a3818..c855bc1c843caa97b1ef1f74e8de58bad0d259e3 100644 (file)
@@ -1,13 +1,15 @@
+; Need to update for multi-segment someday.\r
+\r
 ;.SEGMENT        CodeSegment:  \r
 DONTBR:        LEA R0, AA             \r
        LEA R1, BB              \r
        LEA R2, CC                                                      \r
-       LD R7, R0, ADATA3F      \r
+       LD R7, R0, ADATA3F-AA\r
 \r
-       LD R6, R2, CDATA3F      \r
-       ST R7, R1, BDATA3D      \r
-       ST R7, R1, BDATA3F     \r
-       ST R7, R1, BDATA3C     \r
+       LD R6, R2, CDATA3F-CC\r
+       ST R7, R1, BDATA3D-BB\r
+       ST R7, R1, BDATA3F-BB\r
+       ST R7, R1, BDATA3C-BB\r
        \r
        \r
        ADD R3, R2, -3        \r
@@ -16,48 +18,48 @@ DONTBR:     LEA R0, AA
        STB R7, R4, 0         \r
        \r
        STB R6, R3, 0           \r
-       LD R5, R1, BDATA3A     \r
-       LD R7, R0, ADATA39     \r
-       ST R7, R1, BDATA38      \r
+       LD R5, R1, BDATA3A-BB\r
+       LD R7, R0, ADATA39-AA\r
+       ST R7, R1, BDATA38-BB\r
        \r
-       ST R7, R1, BDATA39      \r
-       ST R7, R1, BDATA3A\r
+       ST R7, R1, BDATA39-BB\r
+       ST R7, R1, BDATA3A-BB\r
         ADD R3, R2, -9\r
        ADD R4, R2, -10\r
        \r
        STB R6, R3, 0                                                   \r
        STB R7, R4, 0           \r
-        ST  R7, R2, CDATA3B    \r
-       LD  R7, R2, CDATA37    \r
+        ST  R7, R2, CDATA3B-CC\r
+       LD  R7, R2, CDATA37-CC\r
          \r
-       LD  R6, R1, BDATA35     \r
-       ST  R6, R2, CDATA37   \r
-       LD  R5, R2, CDATA36     \r
-       LD  R7, R0, ADATA36    \r
+       LD  R6, R1, BDATA35-BB\r
+       ST  R6, R2, CDATA37-CC\r
+       LD  R5, R2, CDATA36-CC\r
+       LD  R7, R0, ADATA36-AA\r
        \r
-        LD  R7, R1, BDATA35    \r
-       LD  R6, R2, CDATA35     \r
-       LD  R7, R0, ADATA37     \r
-       ST  R7, R1, BDATA37   \r
+        LD  R7, R1, BDATA35-BB\r
+       LD  R6, R2, CDATA35-CC\r
+       LD  R7, R0, ADATA37-AA\r
+       ST  R7, R1, BDATA37-BB\r
                                \r
        AND R3, R3, 0           \r
        AND R4, R4, 0           \r
        ADD R3, R3, 11          \r
        ADD R4, R4, -1          \r
 \r
-LOOP:  LD R7, R0, ADATA32                      \r
-       LD R7, R1, BDATA32\r
-        LD R7, R2, CDATA31\r
+LOOP:  LD R7, R0, ADATA32-AA\r
+       LD R7, R1, BDATA32-BB\r
+        LD R7, R2, CDATA31-CC\r
        ADD R3, R3, R4\r
          \r
        BRp LOOP                \r
-       LD R6, R1, BDATA0      \r
-       LD R6, R1, BDATA4       \r
-       LD R6, R1, BDATA10     \r
+       LD R6, R1, BDATA0-BB\r
+       LD R6, R1, BDATA4-BB\r
+       LD R6, R1, BDATA10-BB\r
        \r
-       ST R7, R1, BDATA4       \r
-       ST R7, R1, BDATA11    \r
-       ST R7, R0, ADATA8       \r
+       ST R7, R1, BDATA4-BB\r
+       ST R7, R1, BDATA11-BB\r
+       ST R7, R0, ADATA8-AA\r
 STOP:  BRnzp STOP              \r
 \r
        \r
index 5712b70fdc3ba6e06ac6795af4c64f4939a5d1dc..0c8a3a13b46017ddf028801823a9c5c0f336dcd4 100644 (file)
@@ -71,6 +71,9 @@ EXTRA_DIST += modules/arch/x86/tests/opersize.errwarn
 EXTRA_DIST += modules/arch/x86/tests/opersize.hex
 EXTRA_DIST += modules/arch/x86/tests/opsize-err.asm
 EXTRA_DIST += modules/arch/x86/tests/opsize-err.errwarn
+EXTRA_DIST += modules/arch/x86/tests/overflow.asm
+EXTRA_DIST += modules/arch/x86/tests/overflow.errwarn
+EXTRA_DIST += modules/arch/x86/tests/overflow.hex
 EXTRA_DIST += modules/arch/x86/tests/ret.asm
 EXTRA_DIST += modules/arch/x86/tests/ret.errwarn
 EXTRA_DIST += modules/arch/x86/tests/ret.hex
diff --git a/modules/arch/x86/tests/overflow.asm b/modules/arch/x86/tests/overflow.asm
new file mode 100644 (file)
index 0000000..075824c
--- /dev/null
@@ -0,0 +1,12 @@
+[bits 16]
+mov ax, 'abcd'
+mov ax, 0x1ffff
+mov eax, 0x111111111
+
+dd 0x123456789
+dd -1
+dw 0x12345
+dw -1
+
+jmp 0x1234:0x56789ABC
+jmp dword 0x1234:0x56789ABC
diff --git a/modules/arch/x86/tests/overflow.errwarn b/modules/arch/x86/tests/overflow.errwarn
new file mode 100644 (file)
index 0000000..a648c58
--- /dev/null
@@ -0,0 +1,6 @@
+-:2: warning: value does not fit in 16 bit field
+-:3: warning: value does not fit in 16 bit field
+-:4: warning: value does not fit in 32 bit field
+-:6: warning: value does not fit in 32 bit field
+-:8: warning: value does not fit in 16 bit field
+-:11: warning: value does not fit in 16 bit field
diff --git a/modules/arch/x86/tests/overflow.hex b/modules/arch/x86/tests/overflow.hex
new file mode 100644 (file)
index 0000000..327f010
--- /dev/null
@@ -0,0 +1,37 @@
+b8 
+61 
+62 
+b8 
+ff 
+ff 
+66 
+b8 
+11 
+11 
+11 
+11 
+89 
+67 
+45 
+23 
+ff 
+ff 
+ff 
+ff 
+45 
+23 
+ff 
+ff 
+ea 
+bc 
+9a 
+34 
+12 
+66 
+ea 
+bc 
+9a 
+78 
+56 
+34 
+12 
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e0cc27f8bc9e87731311ea7b2cfd8144d93ce6db 100644 (file)
@@ -0,0 +1 @@
+-:7: warning: value does not fit in 16 bit field
index 085cd2828e336cb20cec659bc0bf621c5c5ccad5..89713cddf52a0446733fc69298efccc88174b328 100644 (file)
@@ -231,11 +231,13 @@ void yasm_x86__parse_seg_prefix(yasm_bytecode *bc, unsigned long segreg,
 void yasm_x86__parse_seg_override(yasm_effaddr *ea, unsigned long segreg,
                                  unsigned long lindex);
 
-int yasm_x86__floatnum_tobytes(const yasm_floatnum *flt, unsigned char **bufp,
-                              unsigned long valsize, const yasm_expr *e);
-int yasm_x86__intnum_tobytes(const yasm_intnum *intn, unsigned char **bufp,
-                            unsigned long valsize, const yasm_expr *e,
-                            const yasm_bytecode *bc, int rel);
+int yasm_x86__floatnum_tobytes(const yasm_floatnum *flt, unsigned char *buf,
+                              size_t destsize, size_t valsize, size_t shift,
+                              int warn, unsigned long lindex);
+int yasm_x86__intnum_tobytes(const yasm_intnum *intn, unsigned char *buf,
+                            size_t destsize, size_t valsize, int shift,
+                            const yasm_bytecode *bc, int rel, int warn,
+                            unsigned long lindex);
 
 unsigned int yasm_x86__get_reg_size(unsigned long reg);
 
index 3031d0ba45a079476c812176dab97d9e334b585d..d484d86879f229f4ca14d845055291616051c6d0 100644 (file)
@@ -956,10 +956,11 @@ x86_bc_tobytes_insn(x86_insn *insn, unsigned char **bufp,
                yasm_internal_error(N_("checkea failed"));
 
            if (ea->disp) {
-               if (output_expr(&ea->disp, bufp, ea->len,
+               if (output_expr(&ea->disp, *bufp, ea->len, ea->len*8, 0,
                                (unsigned long)(*bufp-bufp_orig), sect, bc, 0,
-                               d))
+                               1, d))
                    return 1;
+               *bufp += ea->len;
            } else {
                /* 0 displacement, but we didn't know it before, so we have to
                 * write out 0 value.
@@ -972,10 +973,10 @@ x86_bc_tobytes_insn(x86_insn *insn, unsigned char **bufp,
 
     /* Immediate (if required) */
     if (imm && imm->val) {
-       /* TODO: check imm->len vs. sized len from expr? */
-       if (output_expr(&imm->val, bufp, imm->len,
-                       (unsigned long)(*bufp-bufp_orig), sect, bc, 0, d))
+       if (output_expr(&imm->val, *bufp, imm->len, imm->len*8, 0,
+                       (unsigned long)(*bufp-bufp_orig), sect, bc, 0, 1, d))
            return 1;
+       *bufp += imm->len;
     }
 
     return 0;
@@ -1019,9 +1020,11 @@ x86_bc_tobytes_jmp(x86_jmp *jmp, unsigned char **bufp,
            jmp->target =
                yasm_expr_new(YASM_EXPR_SUB, yasm_expr_expr(jmp->target),
                              yasm_expr_sym(jmp->origin), bc->line);
-           if (output_expr(&jmp->target, bufp, 1,
-                           (unsigned long)(*bufp-bufp_orig), sect, bc, 1, d))
+           if (output_expr(&jmp->target, *bufp, 1, 8, 0,
+                           (unsigned long)(*bufp-bufp_orig), sect, bc, 1, 1,
+                           d))
                return 1;
+           *bufp += 1;
            break;
        case JMP_NEAR_FORCED:
        case JMP_NEAR:
@@ -1039,9 +1042,12 @@ x86_bc_tobytes_jmp(x86_jmp *jmp, unsigned char **bufp,
            jmp->target =
                yasm_expr_new(YASM_EXPR_SUB, yasm_expr_expr(jmp->target),
                              yasm_expr_sym(jmp->origin), bc->line);
-           if (output_expr(&jmp->target, bufp, (opersize == 16) ? 2UL : 4UL,
-                           (unsigned long)(*bufp-bufp_orig), sect, bc, 1, d))
+           i = (opersize == 16) ? 2 : 4;
+           if (output_expr(&jmp->target, *bufp, i, i*8, 0,
+                           (unsigned long)(*bufp-bufp_orig), sect, bc, 1, 1,
+                           d))
                return 1;
+           *bufp += i;
            break;
        case JMP_FAR:
            /* far absolute (4/6 byte depending on operand size) */
@@ -1059,13 +1065,17 @@ x86_bc_tobytes_jmp(x86_jmp *jmp, unsigned char **bufp,
            targetseg = yasm_expr_extract_segment(&jmp->target);
            if (!targetseg)
                yasm_internal_error(N_("could not extract segment for far jump"));
-           if (output_expr(&jmp->target, bufp,
-                           (opersize == 16) ? 2UL : 4UL,
-                           (unsigned long)(*bufp-bufp_orig), sect, bc, 0, d))
+           i = (opersize == 16) ? 2 : 4;
+           if (output_expr(&jmp->target, *bufp, i, i*8, 0,
+                           (unsigned long)(*bufp-bufp_orig), sect, bc, 0, 1,
+                           d))
                return 1;
-           if (output_expr(&targetseg, bufp, 2UL,
-                           (unsigned long)(*bufp-bufp_orig), sect, bc, 0, d))
+           *bufp += i;
+           if (output_expr(&targetseg, *bufp, 2, 2*8, 0,
+                           (unsigned long)(*bufp-bufp_orig), sect, bc, 0, 1,
+                           d))
                return 1;
+           *bufp += 2;
 
            break;
        default:
@@ -1093,32 +1103,27 @@ yasm_x86__bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
 }
 
 int
-yasm_x86__intnum_tobytes(const yasm_intnum *intn, unsigned char **bufp,
-                        unsigned long valsize, const yasm_expr *e,
-                        const yasm_bytecode *bc, int rel)
+yasm_x86__intnum_tobytes(const yasm_intnum *intn, unsigned char *buf,
+                        size_t destsize, size_t valsize, int shift,
+                        const yasm_bytecode *bc, int rel, int warn,
+                        unsigned long lindex)
 {
     if (rel) {
-       long val;
-       if (valsize != 1 && valsize != 2 && valsize != 4)
+       yasm_intnum *relnum, *delta;
+       if (valsize != 8 && valsize != 16 && valsize != 32)
            yasm_internal_error(
                N_("tried to do PC-relative offset from invalid sized value"));
-       val = yasm_intnum_get_uint(intn);
-       val -= bc->len;
-       switch ((unsigned int)valsize) {
-           case 1:
-               YASM_WRITE_8(*bufp, val);
-               break;
-           case 2:
-               YASM_WRITE_16_L(*bufp, val);
-               break;
-           case 4:
-               YASM_WRITE_32_L(*bufp, val);
-               break;
-       }
+       relnum = yasm_intnum_copy(intn);
+       delta = yasm_intnum_new_uint(bc->len);
+       yasm_intnum_calc(relnum, YASM_EXPR_SUB, delta, lindex);
+       yasm_intnum_delete(delta);
+       yasm_intnum_get_sized(relnum, buf, destsize, valsize, shift, 0, warn,
+                             lindex);
+       yasm_intnum_delete(relnum);
     } else {
        /* Write value out. */
-       yasm_intnum_get_sized(intn, *bufp, (size_t)valsize);
-       *bufp += valsize;
+       yasm_intnum_get_sized(intn, buf, destsize, valsize, shift, 0, warn,
+                             lindex);
     }
     return 0;
 }
index 49b95daf4a72882d3f02772dcd0ad882f16b62de..728130f5641d8afadb7368e4a04c26b2a76ab5cd 100644 (file)
@@ -408,8 +408,8 @@ x86_checkea_calc_displen(yasm_expr **ep, unsigned int wordsize, int noreg,
            /* make sure the displacement will fit in 16/32 bits if unsigned,
             * and 8 bits if signed.
             */
-           if (!yasm_intnum_check_size(intn, (size_t)wordsize, 0) &&
-               !yasm_intnum_check_size(intn, 1, 1)) {
+           if (!yasm_intnum_check_size(intn, (size_t)wordsize*8, 0, 0) &&
+               !yasm_intnum_check_size(intn, 8, 0, 1)) {
                yasm__error(e->line, N_("invalid effective address"));
                return 1;
            }
@@ -930,25 +930,16 @@ yasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,
 }
 
 int
-yasm_x86__floatnum_tobytes(const yasm_floatnum *flt, unsigned char **bufp,
-                          unsigned long valsize, const yasm_expr *e)
+yasm_x86__floatnum_tobytes(const yasm_floatnum *flt, unsigned char *buf,
+                          size_t destsize, size_t valsize, size_t shift,
+                          int warn, unsigned long lindex)
 {
-    int fltret;
-
-    if (!yasm_floatnum_check_size(flt, (size_t)valsize)) {
-       yasm__error(e->line, N_("invalid floating point constant size"));
+    if (!yasm_floatnum_check_size(flt, valsize)) {
+       yasm__error(lindex, N_("invalid floating point constant size"));
        return 1;
     }
 
-    fltret = yasm_floatnum_get_sized(flt, *bufp, (size_t)valsize);
-    if (fltret < 0) {
-       yasm__error(e->line, N_("underflow in floating point expression"));
-       return 1;
-    }
-    if (fltret > 0) {
-       yasm__error(e->line, N_("overflow in floating point expression"));
-       return 1;
-    }
-    *bufp += valsize;
+    yasm_floatnum_get_sized(flt, buf, destsize, valsize, shift, 0, warn,
+                           lindex);
     return 0;
 }
index f9e868d96c020679d14bf81c2f7f900e7e01ce98..b6f76582481756f47dba66c5fc7b691fb198974f 100644 (file)
@@ -127,11 +127,11 @@ bin_objfmt_expr_xform(/*@returned@*/ /*@only@*/ yasm_expr *e,
 }
 
 static int
-bin_objfmt_output_expr(yasm_expr **ep, unsigned char **bufp,
-                      unsigned long valsize,
+bin_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
+                      size_t valsize, int shift,
                       /*@unused@*/ unsigned long offset,
                       /*@observer@*/ const yasm_section *sect,
-                      yasm_bytecode *bc, int rel,
+                      yasm_bytecode *bc, int rel, int warn,
                       /*@unused@*/ /*@null@*/ void *d)
 {
     /*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
@@ -145,26 +145,28 @@ bin_objfmt_output_expr(yasm_expr **ep, unsigned char **bufp,
      */
 
     *ep = yasm_expr__level_tree(*ep, 1, 1, NULL, bin_objfmt_expr_xform, NULL,
-                              NULL);
+                               NULL);
 
     /* Handle floating point expressions */
     flt = yasm_expr_get_floatnum(ep);
     if (flt)
-       return cur_arch->floatnum_tobytes(flt, bufp, valsize, *ep);
+       return cur_arch->floatnum_tobytes(flt, buf, destsize, valsize, shift,
+                                         warn, bc->line);
 
     /* Handle integer expressions */
     intn = yasm_expr_get_intnum(ep, NULL);
     if (intn)
-       return cur_arch->intnum_tobytes(intn, bufp, valsize, *ep, bc, rel);
+       return cur_arch->intnum_tobytes(intn, buf, destsize, valsize, shift,
+                                       bc, rel, warn, bc->line);
 
     /* Check for complex float expressions */
     if (yasm_expr__contains(*ep, YASM_EXPR_FLOAT)) {
-       yasm__error((*ep)->line, N_("floating point expression too complex"));
+       yasm__error(bc->line, N_("floating point expression too complex"));
        return 1;
     }
 
     /* Couldn't output, assume it contains an external reference. */
-    yasm__error((*ep)->line,
+    yasm__error(bc->line,
        N_("binary object format does not support external references"));
     return 1;
 }
index f890432db205733b6cb73e96eaf29c1990c0e1de..3efe445d71bd78fcbc5d03cda3bea5c80b5ddb78 100644 (file)
@@ -1,8 +1,8 @@
 -:2: invalid floating point constant size
 -:3: invalid floating point constant size
--:4: overflow in floating point expression
--:5: underflow in floating point expression
+-:4: warning: overflow in floating point expression
+-:5: warning: underflow in floating point expression
 -:8: invalid floating point constant size
 -:9: invalid floating point constant size
--:11: overflow in floating point expression
--:12: underflow in floating point expression
+-:11: warning: overflow in floating point expression
+-:12: warning: underflow in floating point expression
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..dfce6c5de081e94b7b1ba2c0f2926cdca8eda03d 100644 (file)
@@ -0,0 +1,5 @@
+-:2: warning: value does not fit in 8 bit field
+-:3: warning: value does not fit in 16 bit field
+-:4: warning: value does not fit in 32 bit field
+-:5: warning: value does not fit in 64 bit field
+-:6: warning: value does not fit in 80 bit field
index 0d58988ef52806d0ca6eb36448e2e864f438084b..d695172eca2900e2f5b295194330b4c8a9fb62e3 100644 (file)
@@ -282,10 +282,11 @@ coff_objfmt_set_section_addr(yasm_section *sect, /*@null@*/ void *d)
 }
 
 static int
-coff_objfmt_output_expr(yasm_expr **ep, unsigned char **bufp,
-                       unsigned long valsize, unsigned long offset,
+coff_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
+                       size_t valsize, int shift, unsigned long offset,
                        /*@observer@*/ const yasm_section *sect,
-                       yasm_bytecode *bc, int rel, /*@null@*/ void *d)
+                       yasm_bytecode *bc, int rel, int warn,
+                       /*@null@*/ void *d)
 {
     /*@null@*/ coff_objfmt_output_info *info = (coff_objfmt_output_info *)d;
     /*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
@@ -301,7 +302,8 @@ coff_objfmt_output_expr(yasm_expr **ep, unsigned char **bufp,
     /* Handle floating point expressions */
     flt = yasm_expr_get_floatnum(ep);
     if (flt)
-       return cur_arch->floatnum_tobytes(flt, bufp, valsize, *ep);
+       return cur_arch->floatnum_tobytes(flt, buf, destsize, valsize, shift,
+                                         warn, bc->line);
 
     /* Handle integer expressions, with relocation if necessary */
     sym = yasm_expr_extract_symrec(ep, yasm_common_calc_bc_dist);
@@ -309,8 +311,8 @@ coff_objfmt_output_expr(yasm_expr **ep, unsigned char **bufp,
        coff_reloc *reloc;
        yasm_sym_vis vis;
 
-       if (valsize != 4) {
-           yasm__error((*ep)->line, N_("coff: invalid relocation size"));
+       if (valsize != 32) {
+           yasm__error(bc->line, N_("coff: invalid relocation size"));
            return 1;
        }
 
@@ -372,15 +374,16 @@ coff_objfmt_output_expr(yasm_expr **ep, unsigned char **bufp,
     }
     intn = yasm_expr_get_intnum(ep, NULL);
     if (intn)
-       return cur_arch->intnum_tobytes(intn, bufp, valsize, *ep, bc, rel);
+       return cur_arch->intnum_tobytes(intn, buf, destsize, valsize, shift,
+                                       bc, rel, warn, bc->line);
 
     /* Check for complex float expressions */
     if (yasm_expr__contains(*ep, YASM_EXPR_FLOAT)) {
-       yasm__error((*ep)->line, N_("floating point expression too complex"));
+       yasm__error(bc->line, N_("floating point expression too complex"));
        return 1;
     }
 
-    yasm__error((*ep)->line, N_("coff: relocation too complex"));
+    yasm__error(bc->line, N_("coff: relocation too complex"));
     return 1;
 }
 
index 853702f8d9aa085687249f5bde9c72bdf8d606d5..a6bfc6e4561c2b1ef5f82c6d0a70d0b757f2de93 100644 (file)
@@ -171,10 +171,11 @@ elf_objfmt_output_align(FILE *f, unsigned int align)
 
 /* PASS1 */
 static int
-elf_objfmt_output_expr(yasm_expr **ep, unsigned char **bufp,
-                       unsigned long valsize, unsigned long offset,
+elf_objfmt_output_expr(yasm_expr **ep, unsigned char *buf, size_t destsize,
+                       size_t valsize, int shift, unsigned long offset,
                        /*@observer@*/ const yasm_section *sect,
-                       yasm_bytecode *bc, int rel, /*@null@*/ void *d)
+                       yasm_bytecode *bc, int rel, int warn,
+                       /*@null@*/ void *d)
 {
     /*@null@*/ elf_objfmt_output_info *info = (elf_objfmt_output_info *)d;
     /*@dependent@*/ /*@null@*/ const yasm_intnum *intn;
@@ -189,7 +190,8 @@ elf_objfmt_output_expr(yasm_expr **ep, unsigned char **bufp,
     /* Handle floating point expressions */
     flt = yasm_expr_get_floatnum(ep);
     if (flt)
-       return cur_arch->floatnum_tobytes(flt, bufp, valsize, *ep);
+       return cur_arch->floatnum_tobytes(flt, buf, destsize, valsize, shift,
+                                         warn, bc->line);
 
     /* Handle integer expressions, with relocation if necessary */
     sym = yasm_expr_extract_symrec(ep, yasm_common_calc_bc_dist);
@@ -198,8 +200,8 @@ elf_objfmt_output_expr(yasm_expr **ep, unsigned char **bufp,
        yasm_sym_vis vis;
 
        /* XXX: this can't be platform portable */
-       if (valsize != 4) {
-           yasm__error((*ep)->line, N_("elf: invalid relocation size"));
+       if (valsize != 32) {
+           yasm__error(bc->line, N_("elf: invalid relocation size"));
            return 1;
        }
 
@@ -240,15 +242,16 @@ elf_objfmt_output_expr(yasm_expr **ep, unsigned char **bufp,
 
     intn = yasm_expr_get_intnum(ep, NULL);
     if (intn)
-       return cur_arch->intnum_tobytes(intn, bufp, valsize, *ep, bc, rel);
+       return cur_arch->intnum_tobytes(intn, buf, destsize, valsize, shift,
+                                       bc, rel, warn, bc->line);
 
     /* Check for complex float expressions */
     if (yasm_expr__contains(*ep, YASM_EXPR_FLOAT)) {
-       yasm__error((*ep)->line, N_("floating point expression too complex"));
+       yasm__error(bc->line, N_("floating point expression too complex"));
        return 1;
     }
 
-    yasm__error((*ep)->line, N_("elf: relocation too complex"));
+    yasm__error(bc->line, N_("elf: relocation too complex"));
     return 1;
 }