* config/tc-h8300.c (constant_fits_width_p): Trim constant to 32 bits
authorAlan Modra <amodra@gmail.com>
Mon, 27 Feb 2012 06:40:42 +0000 (06:40 +0000)
committerAlan Modra <amodra@gmail.com>
Mon, 27 Feb 2012 06:40:42 +0000 (06:40 +0000)
and sign extend before range tests.
(constant_fits_size_p): Similarly.
(get_specific): Trim X_add_number to 32 bits.
(fix_operand_size): Likewise, and use unsigned test for signed
ranges.

gas/ChangeLog
gas/config/tc-h8300.c

index dbbfcdbb704c89871186c19533c4e7d3b3db2cbf..42d4ff1bcd2af80ebf5a26281c6bebbc47b656aa 100644 (file)
@@ -1,3 +1,12 @@
+2012-02-27  Alan Modra  <amodra@gmail.com>
+
+       * config/tc-h8300.c (constant_fits_width_p): Trim constant to 32 bits
+       and sign extend before range tests.
+       (constant_fits_size_p): Similarly.
+       (get_specific): Trim X_add_number to 32 bits.
+       (fix_operand_size): Likewise, and use unsigned test for signed
+       ranges.
+
 2012-02-27  Alan Modra  <amodra@gmail.com>
 
        * config/tc-crx.c: Include bfd_stdint.h.
index cc46740d3aaa44f796563e58a778f6e524b31791..edfad44d0e1f2542ef43a45010f6a4b94da1e047 100644 (file)
@@ -1,6 +1,6 @@
 /* tc-h8300.c -- Assemble code for the Renesas H8/300
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -558,17 +558,21 @@ skip_colonthing (char *src, int *mode)
 static int
 constant_fits_width_p (struct h8_op *operand, unsigned int width)
 {
-  return ((operand->exp.X_add_number & ~width) == 0
-         || (operand->exp.X_add_number | (offsetT) width) == (offsetT)(~0));
+  offsetT num;
+
+  num = ((operand->exp.X_add_number & 0xffffffff) ^ 0x80000000) - 0x80000000;
+  return (num & ~width) == 0 || (num | width) == ~0;
 }
 
 static int
 constant_fits_size_p (struct h8_op *operand, int size, int no_symbols)
 {
-  offsetT num = operand->exp.X_add_number;
+  offsetT num;
+
   if (no_symbols
       && (operand->exp.X_add_symbol != 0 || operand->exp.X_op_symbol != 0))
     return 0;
+  num = operand->exp.X_add_number & 0xffffffff;
   switch (size)
     {
     case L_2:
@@ -582,11 +586,13 @@ constant_fits_size_p (struct h8_op *operand, int size, int no_symbols)
     case L_5:
       return num >= 1 && num < 32;
     case L_8:
-      return (num & ~0xFF) == 0 || ((unsigned)num | 0x7F) == ~0u;
+      num = (num ^ 0x80000000) - 0x80000000;
+      return (num & ~0xFF) == 0 || (num | 0x7F) == ~0;
     case L_8U:
       return (num & ~0xFF) == 0;
     case L_16:
-      return (num & ~0xFFFF) == 0 || ((unsigned)num | 0x7FFF) == ~0u;
+      num = (num ^ 0x80000000) - 0x80000000;
+      return (num & ~0xFFFF) == 0 || (num | 0x7FFF) == ~0;
     case L_16U:
       return (num & ~0xFFFF) == 0;
     case L_32:
@@ -1184,7 +1190,7 @@ get_specific (const struct h8_instruction *instruction,
                }
              else if (x_mode == IMM && op_mode != IMM)
                {
-                 offsetT num = operands[i].exp.X_add_number;
+                 offsetT num = operands[i].exp.X_add_number & 0xffffffff;
                  if (op_mode == KBIT || op_mode == DBIT)
                    /* This is ok if the immediate value is sensible.  */;
                  else if (op_mode == CONST_2)
@@ -1866,8 +1872,8 @@ fix_operand_size (struct h8_op *operand, int size)
           necessary.  */
        if (Hmode
            && !Nmode 
-           && (operand->exp.X_add_number < -32768
-               || operand->exp.X_add_number > 32767
+           && ((((addressT) operand->exp.X_add_number + 0x8000)
+                & 0xffffffff) > 0xffff
                || operand->exp.X_add_symbol != 0
                || operand->exp.X_op_symbol != 0))
          operand->mode |= L_24;
@@ -1876,9 +1882,8 @@ fix_operand_size (struct h8_op *operand, int size)
        break;
 
       case PCREL:
-       /* This condition is long standing, though somewhat suspect.  */
-       if (operand->exp.X_add_number > -128
-           && operand->exp.X_add_number < 127)
+       if ((((addressT) operand->exp.X_add_number + 0x80)
+            & 0xffffffff) <= 0xff)
          {
            if (operand->exp.X_add_symbol != NULL)
              operand->mode |= bsize;