This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch to clean up h8300 pasing code


This patch is supposed to clean up the h8300 parsing code a bit.
At the moment there are four functions that guess a constant's size:

    - colonmod24 (absolute addresses and some displacements)
    - get_operand (pc-relative addresses)
    - fix_operand_size (short displacements)
    - get_specific (immediates)

As a result, each call to parse_exp() could be followed by one of
three different bits of size-reading code, depending on what kind
of guess was needed:

    - skip_colonthing (immediates - no guess)
    - colonmod24 (addresses and displacements - sometimes guess)
    - inline code (pc-relative addresses - always guess)

I found it difficult to figure out when an operand's size was valid
and when it wasn't.  And my recent fix_operand_size() patch didn't
make things any easier.

Anyway, the patch changes things so that:

    - the parsing code never guesses the size of operands
    - fix_operand_size() guesses the size of everything except immediates
    - get_specific() works out the size of immediates

In other words, there are now two places that guess the size rather than
four.  And since the parsing code no longer guesses the size of anything,
the size-reading code can be folded into parse_exp().

There shouldn't really be a need for a separate call to skip_colonthing()
after these changes.  However, we seem to accept:

        mov.w @(foo,er0:16),r0l

as another way of writing:

        mov.w @(foo:16,er0),r0l

so there is one other call remaining.

One minor change in behaviour: we no longer accept "xx:160" as "xx:16".
I don't think there are any others though.

Patch tested on h8300-elf and h8300-coff.  I also ran it through the sim
& gcc testsuites.  OK to install?

Richard


	* 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().

Index: gas/config/tc-h8300.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-h8300.c,v
retrieving revision 1.33
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.33 tc-h8300.c
*** gas/config/tc-h8300.c	25 Jun 2003 15:31:58 -0000	1.33
--- gas/config/tc-h8300.c	4 Jul 2003 08:14:17 -0000
*************** const char comment_chars[] = ";";
*** 43,56 ****
  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));
  
  int Hmode;
  int Smode;
--- 43,57 ----
  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));
! void h8300sxnmode PARAMS ((int));
! static void pint  PARAMS ((int));
  
  int Hmode;
  int Smode;
*************** int Nmode;
*** 58,64 ****
  int SXmode;
  
  #define PSIZE (Hmode ? L_32 : L_16)
- #define DSYMMODE (Hmode ? L_24 : L_16)
  
  int bsize = L_8;		/* Default branch displacement.  */
  
--- 59,64 ----
*************** static void build_bytes    PARAMS ((cons
*** 339,350 ****
  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 int constant_fits_width_p PARAMS ((struct h8_op *, unsigned int));
  static int constant_fits_size_p PARAMS ((struct h8_op *, int, int));
--- 339,349 ----
  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 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));
*************** parse_reg (src, mode, reg, direction)
*** 474,529 ****
    return 0;
  }
  
  static char *
! parse_exp (s, op)
!      char *s;
!      expressionS *op;
  {
!   char *save = input_line_pointer;
!   char *new;
  
!   input_line_pointer = s;
!   expression (op);
!   if (op->X_op == O_absent)
      as_bad (_("missing operand"));
!   new = input_line_pointer;
    input_line_pointer = save;
!   return new;
  }
  
  static char *
! skip_colonthing (ptr, exp, mode)
!      char *ptr;
!      expressionS *exp ATTRIBUTE_UNUSED;
       int *mode;
  {
!   if (*ptr == ':')
      {
!       ptr++;
        *mode &= ~SIZE;
!       if (ptr[0] == '8' && ! ISDIGIT (ptr[1]))
  	*mode |= L_8;
!       else if (ptr[0] == '2' && ! ISDIGIT (ptr[1]))
  	*mode |= L_2;
!       else if (ptr[0] == '3' && ! ISDIGIT (ptr[1]))
  	*mode |= L_3;
!       else if (ptr[0] == '4' && ! ISDIGIT (ptr[1]))
  	*mode |= L_4;
!       else if (ptr[0] == '5' && ! ISDIGIT (ptr[1]))
  	*mode |= L_5;
!       else if (ptr[0] == '2' && ptr[1] == '4')
  	*mode |= L_24;
!       else if (ptr[0] == '3' && ptr[1] == '2')
  	*mode |= L_32;
!       else if (ptr[0] == '1' && ptr[1] == '6')
  	*mode |= L_16;
        else
  	as_bad (_("invalid operand size requested"));
  
!       while (ISDIGIT (*ptr))
! 	ptr++;
      }
!   return ptr;
  }
  
  /* The many forms of operand:
--- 473,537 ----
    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 (src, op)
!      char *src;
!      struct h8_op *op;
  {
!   char *save;
  
!   save = input_line_pointer;
!   input_line_pointer = src;
!   expression (&op->exp);
!   if (op->exp.X_op == O_absent)
      as_bad (_("missing operand"));
!   src = input_line_pointer;
    input_line_pointer = save;
! 
!   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 (src, mode)
!      char *src;
       int *mode;
  {
!   if (*src == ':')
      {
!       src++;
        *mode &= ~SIZE;
!       if (src[0] == '8' && !ISDIGIT (src[1]))
  	*mode |= L_8;
!       else if (src[0] == '2' && !ISDIGIT (src[1]))
  	*mode |= L_2;
!       else if (src[0] == '3' && !ISDIGIT (src[1]))
  	*mode |= L_3;
!       else if (src[0] == '4' && !ISDIGIT (src[1]))
  	*mode |= L_4;
!       else if (src[0] == '5' && !ISDIGIT (src[1]))
  	*mode |= L_5;
!       else if (src[0] == '2' && src[1] == '4' && !ISDIGIT (src[2]))
  	*mode |= L_24;
!       else if (src[0] == '3' && src[1] == '2' && !ISDIGIT (src[2]))
  	*mode |= L_32;
!       else if (src[0] == '1' && src[1] == '6' && !ISDIGIT (src[2]))
  	*mode |= L_16;
        else
  	as_bad (_("invalid operand size requested"));
  
!       while (ISDIGIT (*src))
! 	src++;
      }
!   return src;
  }
  
  /* The many forms of operand:
*************** skip_colonthing (ptr, exp, mode)
*** 541,575 ****
     @(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;
--- 549,554 ----
*************** get_operand (ptr, op, direction)
*** 707,719 ****
        src++;
        if (*src == '@')
  	{
! 	  src++;
! 	  src = parse_exp (src, &op->exp);
! 
! 	  src = skip_colonthing (src, &op->exp, &op->mode);
! 
! 	  *ptr = src;
! 
  	  if (op->exp.X_add_number >= 0x100)
  	    {
  	      int divisor;
--- 686,692 ----
        src++;
        if (*src == '@')
  	{
! 	  *ptr = parse_exp (src + 1, op);
  	  if (op->exp.X_add_number >= 0x100)
  	    {
  	      int divisor;
*************** get_operand (ptr, op, direction)
*** 731,762 ****
  	    }
  	  else
  	    op->mode = MEMIND;
- 
  	  return;
  	}
  
        if (*src == '-' || *src == '+')
  	{
! 	  char c = *src;
! 	  src++;
! 	  len = parse_reg (src, &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);
! 
  	      return;
  	    }
  
  	  if ((mode & SIZE) != PSIZE)
  	    as_bad (_("Wrong size pointer register for architecture."));
! 	  op->mode = c == '-' ? RDPREDEC : RDPREINC;
  	  op->reg = num;
! 	  *ptr = src + len;
  	  return;
  	}
        if (*src == '(')
--- 704,729 ----
  	    }
  	  else
  	    op->mode = MEMIND;
  	  return;
  	}
  
        if (*src == '-' || *src == '+')
  	{
! 	  len = parse_reg (src + 1, &mode, &num, direction);
  	  if (len == 0)
  	    {
  	      /* Oops, not a reg after all, must be ordinary exp.  */
! 	      op->mode = ABS | direction;
! 	      *ptr = parse_exp (src, op);
  	      return;
  	    }
  
  	  if ((mode & SIZE) != PSIZE)
  	    as_bad (_("Wrong size pointer register for architecture."));
! 
! 	  op->mode = src[0] == '-' ? RDPREDEC : RDPREINC;
  	  op->reg = num;
! 	  *ptr = src + 1 + len;
  	  return;
  	}
        if (*src == '(')
*************** get_operand (ptr, op, direction)
*** 801,815 ****
  
  	  /* Start off assuming a 16 bit offset.  */
  
! 	  src = parse_exp (src, &op->exp);
! 
! 	  src = colonmod24 (op, src);
! 
  	  if (*src == ')')
  	    {
- 	      src++;
  	      op->mode |= ABS | direction;
! 	      *ptr = src;
  	      return;
  	    }
  
--- 768,778 ----
  
  	  /* Start off assuming a 16 bit offset.  */
  
! 	  src = parse_exp (src, op);
  	  if (*src == ')')
  	    {
  	      op->mode |= ABS | direction;
! 	      *ptr = src + 1;
  	      return;
  	    }
  
*************** get_operand (ptr, op, direction)
*** 817,823 ****
  	    {
  	      as_bad (_("expected @(exp, reg16)"));
  	      return;
- 
  	    }
  	  src++;
  
--- 780,785 ----
*************** get_operand (ptr, op, direction)
*** 849,855 ****
  	    }
  	  else
  	    op->mode |= DISP | direction;
! 	  src = skip_colonthing (src, &op->exp, &op->mode);
  
  	  if (*src != ')' && '(')
  	    {
--- 811,817 ----
  	    }
  	  else
  	    op->mode |= DISP | direction;
! 	  src = skip_colonthing (src, &op->mode);
  
  	  if (*src != ')' && '(')
  	    {
*************** get_operand (ptr, op, direction)
*** 857,863 ****
  	      return;
  	    }
  	  *ptr = src + 1;
- 
  	  return;
  	}
        len = parse_reg (src, &mode, &num, direction);
--- 819,824 ----
*************** get_operand (ptr, op, direction)
*** 889,909 ****
  	  /* must be a symbol */
  
  	  op->mode = ABS | direction;
! 	  src = parse_exp (src, &op->exp);
! 
! 	  *ptr = colonmod24 (op, src);
! 
  	  return;
  	}
      }
  
    if (*src == '#')
      {
-       src++;
        op->mode = IMM;
!       src = parse_exp (src, &op->exp);
!       *ptr = skip_colonthing (src, &op->exp, &op->mode);
! 
        return;
      }
    else if (strncmp (src, "mach", 4) == 0 || 
--- 850,864 ----
  	  /* must be a symbol */
  
  	  op->mode = ABS | direction;
! 	  *ptr = parse_exp (src, op);
  	  return;
  	}
      }
  
    if (*src == '#')
      {
        op->mode = IMM;
!       *ptr = parse_exp (src + 1, op);
        return;
      }
    else if (strncmp (src, "mach", 4) == 0 || 
*************** get_operand (ptr, op, direction)
*** 918,952 ****
      }
    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;
      }
  }
  
--- 873,880 ----
      }
    else
      {
!       op->mode = PCREL;
!       *ptr = parse_exp (src, op);
      }
  }
  
*************** get_mova_operands (char *op_end, struct 
*** 1010,1017 ****
      goto error;
    ptr += 3;
    operand[0].mode = 0;
!   ptr = parse_exp (ptr, &operand[0].exp);
!   ptr = colonmod24 (operand + 0, ptr);
  
    if (*ptr !=',')
      goto error;
--- 938,944 ----
      goto error;
    ptr += 3;
    operand[0].mode = 0;
!   ptr = parse_exp (ptr, &operand[0]);
  
    if (*ptr !=',')
      goto error;
*************** clever_message (instruction, operand)
*** 1880,1890 ****
  }
  
  
! /* Adjust OPERAND's value and size given that it is accessing a field
!    of 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
     displacement in an @(d:2,ERn) operand.  */
  
  static void
--- 1807,1817 ----
  }
  
  
! /* If OPERAND is part of an address, adjust its size and value given
!    that it addresses SIZE bytes.
  
!    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
*************** fix_operand_size (operand, size)
*** 1892,1903 ****
       struct h8_op *operand;
       int size;
  {
!   if ((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
  	  && (operand->exp.X_add_number == size
  	      || operand->exp.X_add_number == size * 2
  	      || operand->exp.X_add_number == size * 3))
--- 1819,1829 ----
       struct h8_op *operand;
       int size;
  {
!   if (SXmode && (operand->mode & MODE) == DISP)
      {
        /* If the user didn't specify an operand width, see if we
  	 can use @(d:2,ERn).  */
!       if ((operand->mode & SIZE) == 0
  	  && (operand->exp.X_add_number == size
  	      || operand->exp.X_add_number == size * 2
  	      || operand->exp.X_add_number == size * 3))
*************** fix_operand_size (operand, size)
*** 1913,1920 ****
  	}
      }
  
-   /* 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)
        {
--- 1839,1844 ----
*************** fix_operand_size (operand, size)
*** 1923,1929 ****
        case INDEXW:
        case INDEXL:
        case ABS:
! 	operand->mode |= L_16;
  	break;
        }
  }
--- 1847,1872 ----
        case INDEXW:
        case INDEXL:
        case ABS:
! 	/* 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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]