* config/tc-h8300.c (h8300sxnmode): Add prototype.
authorRichard Sandiford <rdsandiford@googlemail.com>
Mon, 7 Jul 2003 09:33:02 +0000 (09:33 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Mon, 7 Jul 2003 09:33:02 +0000 (09:33 +0000)
(DSYMMODE): Remove.
(parse_exp): Replace expressionS argument with a h8_op.  Parse the
operand size as well.
(skip_colonthing): Remove unused expression argument.  Tighten checks
for 2-digit sizes.
(colonmod24): Remove.
(get_mova_operands): Combine calls to parse_exp and skip_colonthing.
(get_operand): Likewise.  Use the standard code to read the size of
pc-relative operands.
(fix_operand_size): Include the size-guessing logic that used to be
in colonmod24 and get_operand.  Don't apply dd:2 optimizations to
offsets with a symbolic component.

testsuite/
* gas/h8300/h8sx_disp2.[sd]: Add tests for symbolic displacements.

gas/ChangeLog
gas/config/tc-h8300.c
gas/testsuite/ChangeLog
gas/testsuite/gas/h8300/h8sx_disp2.d
gas/testsuite/gas/h8300/h8sx_disp2.s

index 2d11c7d..f039583 100644 (file)
@@ -1,3 +1,19 @@
+2003-07-07  Richard Sandiford  <rsandifo@redhat.com>
+
+       * config/tc-h8300.c (h8300sxnmode): Add prototype.
+       (DSYMMODE): Remove.
+       (parse_exp): Replace expressionS argument with a h8_op.  Parse the
+       operand size as well.
+       (skip_colonthing): Remove unused expression argument.  Tighten checks
+       for 2-digit sizes.
+       (colonmod24): Remove.
+       (get_mova_operands): Combine calls to parse_exp and skip_colonthing.
+       (get_operand): Likewise.  Use the standard code to read the size of
+       pc-relative operands.
+       (fix_operand_size): Include the size-guessing logic that used to be
+       in colonmod24 and get_operand.  Don't apply dd:2 optimizations to
+       offsets with a symbolic component.
+
 2003-07-04  Nick Clifton  <nickc@redhat.com>
 
        * config/tc-i386.c (tc_x86_regname_to_dw2regnum): Use ARRAY_SIZE
index 646b69e..4354b1a 100644 (file)
@@ -43,14 +43,15 @@ const char comment_chars[] = ";";
 const char line_comment_chars[] = "#";
 const char line_separator_chars[] = "";
 
-void cons        PARAMS ((int));
-void sbranch     PARAMS ((int));
-void h8300hmode  PARAMS ((int));
-void h8300smode  PARAMS ((int));
-void h8300hnmode PARAMS ((int));
-void h8300snmode PARAMS ((int));
-void h8300sxmode PARAMS ((int));
-static void pint PARAMS ((int));
+void cons         PARAMS ((int));
+void sbranch      PARAMS ((int));
+void h8300hmode   PARAMS ((int));
+void h8300smode   PARAMS ((int));
+void h8300hnmode  PARAMS ((int));
+void h8300snmode  PARAMS ((int));
+void h8300sxmode  PARAMS ((int));
+void h8300sxnmode PARAMS ((int));
+static void pint  PARAMS ((int));
 
 int Hmode;
 int Smode;
@@ -58,7 +59,6 @@ int Nmode;
 int SXmode;
 
 #define PSIZE (Hmode ? L_32 : L_16)
-#define DSYMMODE (Hmode ? L_24 : L_16)
 
 int bsize = L_8;               /* Default branch displacement.  */
 
@@ -339,12 +339,11 @@ static void build_bytes    PARAMS ((const struct h8_instruction *, struct h8_op
 static void do_a_fix_imm   PARAMS ((int, int, struct h8_op *, int));
 static void check_operand  PARAMS ((struct h8_op *, unsigned int, char *));
 static const struct h8_instruction * get_specific PARAMS ((const struct h8_instruction *, struct h8_op *, int));
-static char * get_operands PARAMS ((unsigned, char *, struct h8_op *));
-static void   get_operand  PARAMS ((char **, struct h8_op *, int));
-static char * skip_colonthing PARAMS ((char *, expressionS *, int *));
-static char * parse_exp PARAMS ((char *, expressionS *));
-static int    parse_reg PARAMS ((char *, op_type *, unsigned *, int));
-char * colonmod24 PARAMS ((struct h8_op *, char *));
+static char *get_operands PARAMS ((unsigned, char *, struct h8_op *));
+static void get_operand PARAMS ((char **, struct h8_op *, int));
+static int parse_reg PARAMS ((char *, op_type *, unsigned *, int));
+static char *skip_colonthing PARAMS ((char *, int *));
+static char *parse_exp PARAMS ((char *, struct h8_op *));
 
 static int constant_fits_width_p PARAMS ((struct h8_op *, unsigned int));
 static int constant_fits_size_p PARAMS ((struct h8_op *, int, int));
@@ -474,56 +473,65 @@ parse_reg (src, mode, reg, direction)
   return 0;
 }
 
+
+/* Parse an immediate or address-related constant and store it in OP.
+   If the user also specifies the operand's size, store that size
+   in OP->MODE, otherwise leave it for later code to decide.  */
+
 static char *
-parse_exp (s, op)
-     char *s;
-     expressionS *op;
+parse_exp (src, op)
+     char *src;
+     struct h8_op *op;
 {
-  char *save = input_line_pointer;
-  char *new;
+  char *save;
 
-  input_line_pointer = s;
-  expression (op);
-  if (op->X_op == O_absent)
+  save = input_line_pointer;
+  input_line_pointer = src;
+  expression (&op->exp);
+  if (op->exp.X_op == O_absent)
     as_bad (_("missing operand"));
-  new = input_line_pointer;
+  src = input_line_pointer;
   input_line_pointer = save;
-  return new;
+
+  return skip_colonthing (src, &op->mode);
 }
 
+
+/* If SRC starts with an explicit operand size, skip it and store the size
+   in *MODE.  Leave *MODE unchanged otherwise.  */
+
 static char *
-skip_colonthing (ptr, exp, mode)
-     char *ptr;
-     expressionS *exp ATTRIBUTE_UNUSED;
+skip_colonthing (src, mode)
+     char *src;
      int *mode;
 {
-  if (*ptr == ':')
+  if (*src == ':')
     {
-      ptr++;
+      src++;
       *mode &= ~SIZE;
-      if (ptr[0] == '8' && ! ISDIGIT (ptr[1]))
+      if (src[0] == '8' && !ISDIGIT (src[1]))
        *mode |= L_8;
-      else if (ptr[0] == '2' && ! ISDIGIT (ptr[1]))
+      else if (src[0] == '2' && !ISDIGIT (src[1]))
        *mode |= L_2;
-      else if (ptr[0] == '3' && ! ISDIGIT (ptr[1]))
+      else if (src[0] == '3' && !ISDIGIT (src[1]))
        *mode |= L_3;
-      else if (ptr[0] == '4' && ! ISDIGIT (ptr[1]))
+      else if (src[0] == '4' && !ISDIGIT (src[1]))
        *mode |= L_4;
-      else if (ptr[0] == '5' && ! ISDIGIT (ptr[1]))
+      else if (src[0] == '5' && !ISDIGIT (src[1]))
        *mode |= L_5;
-      else if (ptr[0] == '2' && ptr[1] == '4')
+      else if (src[0] == '2' && src[1] == '4' && !ISDIGIT (src[2]))
        *mode |= L_24;
-      else if (ptr[0] == '3' && ptr[1] == '2')
+      else if (src[0] == '3' && src[1] == '2' && !ISDIGIT (src[2]))
        *mode |= L_32;
-      else if (ptr[0] == '1' && ptr[1] == '6')
+      else if (src[0] == '1' && src[1] == '6' && !ISDIGIT (src[2]))
        *mode |= L_16;
       else
        as_bad (_("invalid operand size requested"));
 
-      while (ISDIGIT (*ptr))
-       ptr++;
+      while (ISDIGIT (*src))
+       src++;
     }
-  return ptr;
+  return src;
 }
 
 /* The many forms of operand:
@@ -541,35 +549,6 @@ skip_colonthing (ptr, exp, mode)
    @(exp:[8], pc)      pc rel
    @@aa[:8]            memory indirect.  */
 
-char *
-colonmod24 (op, src)
-     struct h8_op *op;
-     char *src;
-{
-  int mode = 0;
-  src = skip_colonthing (src, &op->exp, &mode);
-
-  if (!mode)
-    {
-      /* If the operand is a 16-bit constant integer, leave fix_operand_size
-        to calculate its size.  Otherwise choose a default here.  */
-      if (op->exp.X_add_number < -32768
-         || op->exp.X_add_number > 32767)
-       {
-         if (Hmode)
-           mode = L_24;
-         else
-           mode = L_16;
-       }
-      else if (op->exp.X_add_symbol
-              || op->exp.X_op_symbol)
-       mode = DSYMMODE;
-    }
-
-  op->mode |= mode;
-  return src;
-}
-
 static int
 constant_fits_width_p (operand, width)
      struct h8_op *operand;
@@ -707,13 +686,7 @@ get_operand (ptr, op, direction)
       src++;
       if (*src == '@')
        {
-         src++;
-         src = parse_exp (src, &op->exp);
-
-         src = skip_colonthing (src, &op->exp, &op->mode);
-
-         *ptr = src;
-
+         *ptr = parse_exp (src + 1, op);
          if (op->exp.X_add_number >= 0x100)
            {
              int divisor;
@@ -731,32 +704,26 @@ get_operand (ptr, op, direction)
            }
          else
            op->mode = MEMIND;
-
          return;
        }
 
       if (*src == '-' || *src == '+')
        {
-         char c = *src;
-         src++;
-         len = parse_reg (src, &mode, &num, direction);
+         len = parse_reg (src + 1, &mode, &num, direction);
          if (len == 0)
            {
              /* Oops, not a reg after all, must be ordinary exp.  */
-             src--;
-             /* Must be a symbol.  */
-             op->mode = ABS | PSIZE | direction;
-             *ptr = skip_colonthing (parse_exp (src, &op->exp),
-                                     &op->exp, &op->mode);
-
+             op->mode = ABS | direction;
+             *ptr = parse_exp (src, op);
              return;
            }
 
          if ((mode & SIZE) != PSIZE)
            as_bad (_("Wrong size pointer register for architecture."));
-         op->mode = c == '-' ? RDPREDEC : RDPREINC;
+
+         op->mode = src[0] == '-' ? RDPREDEC : RDPREINC;
          op->reg = num;
-         *ptr = src + len;
+         *ptr = src + 1 + len;
          return;
        }
       if (*src == '(')
@@ -801,15 +768,11 @@ get_operand (ptr, op, direction)
 
          /* Start off assuming a 16 bit offset.  */
 
-         src = parse_exp (src, &op->exp);
-
-         src = colonmod24 (op, src);
-
+         src = parse_exp (src, op);
          if (*src == ')')
            {
-             src++;
              op->mode |= ABS | direction;
-             *ptr = src;
+             *ptr = src + 1;
              return;
            }
 
@@ -817,7 +780,6 @@ get_operand (ptr, op, direction)
            {
              as_bad (_("expected @(exp, reg16)"));
              return;
-
            }
          src++;
 
@@ -849,7 +811,7 @@ get_operand (ptr, op, direction)
            }
          else
            op->mode |= DISP | direction;
-         src = skip_colonthing (src, &op->exp, &op->mode);
+         src = skip_colonthing (src, &op->mode);
 
          if (*src != ')' && '(')
            {
@@ -857,7 +819,6 @@ get_operand (ptr, op, direction)
              return;
            }
          *ptr = src + 1;
-
          return;
        }
       len = parse_reg (src, &mode, &num, direction);
@@ -889,21 +850,15 @@ get_operand (ptr, op, direction)
          /* must be a symbol */
 
          op->mode = ABS | direction;
-         src = parse_exp (src, &op->exp);
-
-         *ptr = colonmod24 (op, src);
-
+         *ptr = parse_exp (src, op);
          return;
        }
     }
 
   if (*src == '#')
     {
-      src++;
       op->mode = IMM;
-      src = parse_exp (src, &op->exp);
-      *ptr = skip_colonthing (src, &op->exp, &op->mode);
-
+      *ptr = parse_exp (src + 1, op);
       return;
     }
   else if (strncmp (src, "mach", 4) == 0 || 
@@ -918,35 +873,8 @@ get_operand (ptr, op, direction)
     }
   else
     {
-      src = parse_exp (src, &op->exp);
-      /* Trailing ':' size ? */
-      if (*src == ':')
-       {
-         if (src[1] == '1' && src[2] == '6')
-           {
-             op->mode = PCREL | L_16;
-             src += 3;
-           }
-         else if (src[1] == '8')
-           {
-             op->mode = PCREL | L_8;
-             src += 2;
-           }
-         else
-           as_bad (_("expect :8 or :16 here"));
-       }
-      else
-       {
-         int val = op->exp.X_add_number;
-
-         op->mode = PCREL;
-         if (-128 < val && val < 127)
-           op->mode |= L_8;
-         else
-           op->mode |= L_16;
-       }
-
-      *ptr = src;
+      op->mode = PCREL;
+      *ptr = parse_exp (src, op);
     }
 }
 
@@ -1010,8 +938,7 @@ get_mova_operands (char *op_end, struct h8_op *operand)
     goto error;
   ptr += 3;
   operand[0].mode = 0;
-  ptr = parse_exp (ptr, &operand[0].exp);
-  ptr = colonmod24 (operand + 0, ptr);
+  ptr = parse_exp (ptr, &operand[0]);
 
   if (*ptr !=',')
     goto error;
@@ -1880,11 +1807,11 @@ clever_message (instruction, operand)
 }
 
 
-/* Adjust OPERAND's value and size given that it is accessing a field
-   of SIZE bytes.
+/* If OPERAND is part of an address, adjust its size and value given
+   that it addresses SIZE bytes.
 
-   This function handles the choice between @(d:2,ERn) and @(d:16,ERn)
-   when no size is explicitly given.  It also scales down the assembly-level
+   This function decides how big non-immediate constants are when no
+   size was explicitly given.  It also scales down the assembly-level
    displacement in an @(d:2,ERn) operand.  */
 
 static void
@@ -1892,12 +1819,13 @@ fix_operand_size (operand, size)
      struct h8_op *operand;
      int size;
 {
-  if ((operand->mode & MODE) == DISP)
+  if (SXmode && (operand->mode & MODE) == DISP)
     {
       /* If the user didn't specify an operand width, see if we
         can use @(d:2,ERn).  */
-      if (SXmode
-         && (operand->mode & SIZE) == 0
+      if ((operand->mode & SIZE) == 0
+         && operand->exp.X_add_symbol == 0
+         && operand->exp.X_op_symbol == 0
          && (operand->exp.X_add_number == size
              || operand->exp.X_add_number == size * 2
              || operand->exp.X_add_number == size * 3))
@@ -1913,8 +1841,6 @@ fix_operand_size (operand, size)
        }
     }
 
-  /* If the operand needs a size but doesn't have one yet, it must be
-     a 16-bit integer (see colonmod24).  */
   if ((operand->mode & SIZE) == 0)
     switch (operand->mode & MODE)
       {
@@ -1923,7 +1849,26 @@ fix_operand_size (operand, size)
       case INDEXW:
       case INDEXL:
       case ABS:
-       operand->mode |= L_16;
+       /* Pick a 24-bit address unless we know that a 16-bit address
+          is safe.  get_specific() will relax L_24 into L_32 where
+          necessary.  */
+       if (Hmode
+           && (operand->exp.X_add_number < -32768
+               || operand->exp.X_add_number > 32767
+               || operand->exp.X_add_symbol != 0
+               || operand->exp.X_op_symbol != 0))
+         operand->mode |= L_24;
+       else
+         operand->mode |= L_16;
+       break;
+
+      case PCREL:
+       /* This condition is long standing, though somewhat suspect.  */
+       if (operand->exp.X_add_number > -128
+           && operand->exp.X_add_number < 127)
+         operand->mode |= L_8;
+       else
+         operand->mode |= L_16;
        break;
       }
 }
index 5a878a5..2083d32 100644 (file)
@@ -1,3 +1,7 @@
+2003-07-07  Richard Sandiford  <rsandifo@redhat.com>
+
+       * gas/h8300/h8sx_disp2.[sd]: Add tests for symbolic displacements.
+
 2003-07-04  Alan Modra  <amodra@bigpond.net.au>
 
        * gas/ppc/test2elf64.s: Rename to..
index b1def76..a3c712c 100644 (file)
@@ -5,33 +5,42 @@
 Disassembly of section \.text:
 
 0+00 <\.text>:
- * 0:  01 75 68 08 *   01 75 68 08 80 02 add.b #0x2,@\(0x1:2,r0\)
- * 4:  80 02 *
- * 6:  01 76 68 08 *   01 76 68 08 80 02 add.b #0x2,@\(0x2:2,r0\)
- * a:  80 02 *
- * c:  01 77 68 08 *   01 77 68 08 80 02 add.b #0x2,@\(0x3:2,r0\)
- *10:  80 02 *
- *12:  01 74 6e 08 *   01 74 6e 08 00 04 80 02 add.b   #0x2,@\(0x4:16,r0\)
- *16:  00 04 80 02 *
- *1a:  01 5e c0 10 *   01 5e c0 10 00 01 00 02 add.w   #0x2,@\(0x1:16,r0\)
- *1e:  00 01 00 02 *
- *22:  01 5e 10 10 *   01 5e 10 10 00 02 add.w #0x2,@\(0x2:2,r0\)
- *26:  00 02 *
- *28:  01 5e 20 10 *   01 5e 20 10 00 02 add.w #0x2,@\(0x4:2,r0\)
- *2c:  00 02 *
- *2e:  01 5e 30 10 *   01 5e 30 10 00 02 add.w #0x2,@\(0x6:2,r0\)
- *32:  00 02 *
- *34:  01 5e c0 10 *   01 5e c0 10 00 08 00 02 add.w   #0x2,@\(0x8:16,r0\)
- *38:  00 08 00 02 *
- *3c:  01 0e c0 10 *   01 0e c0 10 00 01 00 02 add.l   #0x2,@\(0x1:16,r0\)
- *40:  00 01 00 02 *
- *44:  01 0e c0 10 *   01 0e c0 10 00 02 00 02 add.l   #0x2,@\(0x2:16,r0\)
- *48:  00 02 00 02 *
- *4c:  01 0e 10 10 *   01 0e 10 10 00 02 add.l #0x2,@\(0x4:2,r0\)
- *50:  00 02 *
- *52:  01 0e 20 10 *   01 0e 20 10 00 02 add.l #0x2,@\(0x8:2,r0\)
- *56:  00 02 *
- *58:  01 0e 30 10 *   01 0e 30 10 00 02 add.l #0x2,@\(0xc:2,r0\)
- *5c:  00 02 *
- *5e:  01 0e c0 10 *   01 0e c0 10 00 10 00 02 add.l   #0x2,@\(0x10:16,r0\)
- *62:  00 10 00 02 *
+ .*:   01 75 68 08 *   01 75 68 08 80 02 add.b #0x2,@\(0x1:2,r0\)
+ .*:   80 02 *
+ .*:   01 76 68 08 *   01 76 68 08 80 02 add.b #0x2,@\(0x2:2,r0\)
+ .*:   80 02 *
+ .*:   01 77 68 08 *   01 77 68 08 80 02 add.b #0x2,@\(0x3:2,r0\)
+ .*:   80 02 *
+ .*:   01 74 6e 08 *   01 74 6e 08 00 04 80 02 add.b   #0x2,@\(0x4:16,r0\)
+ .*:   00 04 80 02 *
+ .*:   78 04 6a 28 *   78 04 6a 28 00 00 00 00 80 02 add.b     #0x2,@\(0x0:32,r0\)
+ .*:   00 00 00 00 *
+ .*:   80 02 *
+ .*:   01 5e c0 10 *   01 5e c0 10 00 01 00 02 add.w   #0x2,@\(0x1:16,r0\)
+ .*:   00 01 00 02 *
+ .*:   01 5e 10 10 *   01 5e 10 10 00 02 add.w #0x2,@\(0x2:2,r0\)
+ .*:   00 02 *
+ .*:   01 5e 20 10 *   01 5e 20 10 00 02 add.w #0x2,@\(0x4:2,r0\)
+ .*:   00 02 *
+ .*:   01 5e 30 10 *   01 5e 30 10 00 02 add.w #0x2,@\(0x6:2,r0\)
+ .*:   00 02 *
+ .*:   01 5e c0 10 *   01 5e c0 10 00 08 00 02 add.w   #0x2,@\(0x8:16,r0\)
+ .*:   00 08 00 02 *
+ .*:   01 5e c8 10 *   01 5e c8 10 00 00 00 00 00 02 add.w     #0x2,@\(0x0:32,r0\)
+ .*:   00 00 00 00 *
+ .*:   00 02 *
+ .*:   01 0e c0 10 *   01 0e c0 10 00 01 00 02 add.l   #0x2,@\(0x1:16,r0\)
+ .*:   00 01 00 02 *
+ .*:   01 0e c0 10 *   01 0e c0 10 00 02 00 02 add.l   #0x2,@\(0x2:16,r0\)
+ .*:   00 02 00 02 *
+ .*:   01 0e 10 10 *   01 0e 10 10 00 02 add.l #0x2,@\(0x4:2,r0\)
+ .*:   00 02 *
+ .*:   01 0e 20 10 *   01 0e 20 10 00 02 add.l #0x2,@\(0x8:2,r0\)
+ .*:   00 02 *
+ .*:   01 0e 30 10 *   01 0e 30 10 00 02 add.l #0x2,@\(0xc:2,r0\)
+ .*:   00 02 *
+ .*:   01 0e c0 10 *   01 0e c0 10 00 10 00 02 add.l   #0x2,@\(0x10:16,r0\)
+ .*:   00 10 00 02 *
+ .*:   01 0e c8 10 *   01 0e c8 10 00 00 00 00 00 02 add.l     #0x2,@\(0x0:32,r0\)
+ .*:   00 00 00 00 *
+ .*:   00 02 *
index f3d8393..5f6b37d 100644 (file)
@@ -3,12 +3,14 @@
        add.b   #2,@(2,er0)     ; L_2
        add.b   #2,@(3,er0)     ; L_2
        add.b   #2,@(4,er0)     ; L_16
+       add.b   #2,@(foo+1,er0) ; L_32
 
        add.w   #2,@(1,er0)     ; L_16
        add.w   #2,@(2,er0)     ; L_2
        add.w   #2,@(4,er0)     ; L_2
        add.w   #2,@(6,er0)     ; L_2
        add.w   #2,@(8,er0)     ; L_16
+       add.w   #2,@(foo+2,er0) ; L_32
 
        add.l   #2,@(1,er0)     ; L_16
        add.l   #2,@(2,er0)     ; L_16
@@ -16,3 +18,4 @@
        add.l   #2,@(8,er0)     ; L_2
        add.l   #2,@(12,er0)    ; L_2
        add.l   #2,@(16,er0)    ; L_16
+       add.l   #2,@(foo+4,er0) ; L_32