gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gas / config / m68k-parse.y
index dea1a53865010adcbf0e4366d0a0e827d2ebf126..11874298c0f4b6aaf203578e3d712ba42901ff13 100644 (file)
@@ -1,12 +1,12 @@
 /* m68k.y -- bison grammar for m68k operand parsing
-   Copyright (C) 1995 Free Software Foundation, Inc.
+   Copyright (C) 1995-2020 Free Software Foundation, Inc.
    Written by Ken Raeburn and Ian Lance Taylor, Cygnus Support
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
@@ -16,8 +16,8 @@
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 
 /* This file holds a bison grammar to parse m68k operands.  The m68k
    has a complicated operand syntax, and gas supports two main
 #include "as.h"
 #include "tc-m68k.h"
 #include "m68k-parse.h"
+#include "safe-ctype.h"
 
 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror,
-   etc), as well as gratuitiously global symbol names If other parser
+   etc), as well as gratuitously global symbol names If other parser
    generators (bison, byacc, etc) produce additional global names that
    conflict at link time, then those parser generators need to be
-   fixed instead of adding those names to this list. */
+   fixed instead of adding those names to this list.  */
 
 #define        yymaxdepth m68k_maxdepth
 #define        yyparse m68k_parse
 #define        yylval  m68k_lval
 #define        yychar  m68k_char
 #define        yydebug m68k_debug
-#define        yypact  m68k_pact       
-#define        yyr1    m68k_r1                 
-#define        yyr2    m68k_r2                 
-#define        yydef   m68k_def                
-#define        yychk   m68k_chk                
-#define        yypgo   m68k_pgo                
-#define        yyact   m68k_act                
+#define        yypact  m68k_pact
+#define        yyr1    m68k_r1
+#define        yyr2    m68k_r2
+#define        yydef   m68k_def
+#define        yychk   m68k_chk
+#define        yypgo   m68k_pgo
+#define        yyact   m68k_act
 #define        yyexca  m68k_exca
 #define yyerrflag m68k_errflag
 #define yynerrs        m68k_nerrs
@@ -81,8 +82,9 @@
 
 /* Internal functions.  */
 
-static int yylex PARAMS (());
-static void yyerror PARAMS ((const char *));
+static enum m68k_register m68k_reg_parse (char **);
+static int yylex (void);
+static void yyerror (const char *);
 
 /* The parser sets fields pointed to by this global variable.  */
 static struct m68k_op *op;
@@ -96,6 +98,7 @@ static struct m68k_op *op;
   struct m68k_exp exp;
   unsigned long mask;
   int onereg;
+  int trailing_ampersand;
 }
 
 %token <reg> DR AR FPR FPCR LPC ZAR ZDR LZPC CREG
@@ -107,6 +110,7 @@ static struct m68k_op *op;
 %type <exp> optcexpr optexprc
 %type <mask> reglist ireglist reglistpair
 %type <onereg> reglistreg
+%type <trailing_ampersand> optional_ampersand
 
 %%
 
@@ -114,14 +118,38 @@ static struct m68k_op *op;
 
 operand:
          generic_operand
-       | motorola_operand
-       | mit_operand
+       | motorola_operand optional_ampersand
+               {
+                 op->trailing_ampersand = $2;
+               }
+       | mit_operand optional_ampersand
+               {
+                 op->trailing_ampersand = $2;
+               }
+       ;
+
+/* A trailing ampersand(for MAC/EMAC mask addressing).  */
+optional_ampersand:
+       /* empty */
+               { $$ = 0; }
+       | '&'
+               { $$ = 1; }
        ;
 
 /* A generic operand.  */
 
 generic_operand:
-         DR
+         '<' '<'
+               {
+                 op->mode = LSH;
+               }
+
+       | '>' '>'
+               {
+                 op->mode = RSH;
+               }
+
+       | DR
                {
                  op->mode = DREG;
                  op->reg = $1;
@@ -199,6 +227,16 @@ motorola_operand:
                  else
                    op->mode = DISP;
                }
+       | '(' zapc ',' EXPR ')'
+               {
+                 op->reg = $2;
+                 op->disp = $4;
+                 if (($2 >= ZADDR0 && $2 <= ZADDR7)
+                     || $2 == ZPC)
+                   op->mode = BASE;
+                 else
+                   op->mode = DISP;
+               }
        | EXPR '(' zapc ')'
                {
                  op->reg = $3;
@@ -234,7 +272,7 @@ motorola_operand:
        | '(' EXPR ',' zapc ',' zpc ')'
                {
                  if ($4 == PC || $4 == ZPC)
-                   yyerror ("syntax error");
+                   yyerror (_("syntax error"));
                  op->mode = BASE;
                  op->reg = $6;
                  op->disp = $2;
@@ -249,6 +287,12 @@ motorola_operand:
                  op->disp = $2;
                  op->index = $4;
                }
+       | '(' zdireg ',' EXPR ')'
+               {
+                 op->mode = BASE;
+                 op->disp = $4;
+                 op->index = $2;
+               }
        | EXPR '(' zapc ',' zireg ')'
                {
                  op->mode = BASE;
@@ -265,7 +309,7 @@ motorola_operand:
        | EXPR '(' zapc ',' zpc ')'
                {
                  if ($3 == PC || $3 == ZPC)
-                   yyerror ("syntax error");
+                   yyerror (_("syntax error"));
                  op->mode = BASE;
                  op->reg = $5;
                  op->disp = $1;
@@ -276,7 +320,7 @@ motorola_operand:
        | '(' zapc ',' zpc ')'
                {
                  if ($2 == PC || $2 == ZPC)
-                   yyerror ("syntax error");
+                   yyerror (_("syntax error"));
                  op->mode = BASE;
                  op->reg = $4;
                  op->index.reg = $2;
@@ -342,7 +386,7 @@ motorola_operand:
        | '(' '[' EXPR ',' zapc ',' zpc ']' optcexpr ')'
                {
                  if ($5 == PC || $5 == ZPC)
-                   yyerror ("syntax error");
+                   yyerror (_("syntax error"));
                  op->mode = PRE;
                  op->reg = $7;
                  op->disp = $3;
@@ -354,7 +398,7 @@ motorola_operand:
        | '(' '[' zapc ',' zpc ']' optcexpr ')'
                {
                  if ($3 == PC || $3 == ZPC)
-                   yyerror ("syntax error");
+                   yyerror (_("syntax error"));
                  op->mode = PRE;
                  op->reg = $5;
                  op->index.reg = $3;
@@ -379,7 +423,7 @@ mit_operand:
                {
                  /* We use optzapc to avoid a shift/reduce conflict.  */
                  if ($1 < ADDR0 || $1 > ADDR7)
-                   yyerror ("syntax error");
+                   yyerror (_("syntax error"));
                  op->mode = AINDR;
                  op->reg = $1;
                }
@@ -387,7 +431,7 @@ mit_operand:
                {
                  /* We use optzapc to avoid a shift/reduce conflict.  */
                  if ($1 < ADDR0 || $1 > ADDR7)
-                   yyerror ("syntax error");
+                   yyerror (_("syntax error"));
                  op->mode = AINC;
                  op->reg = $1;
                }
@@ -395,7 +439,7 @@ mit_operand:
                {
                  /* We use optzapc to avoid a shift/reduce conflict.  */
                  if ($1 < ADDR0 || $1 > ADDR7)
-                   yyerror ("syntax error");
+                   yyerror (_("syntax error"));
                  op->mode = ADEC;
                  op->reg = $1;
                }
@@ -596,7 +640,10 @@ ireglist:
 reglistpair:
          reglistreg '-' reglistreg
                {
-                 $$ = (1 << ($3 + 1)) - 1 - ((1 << $1) - 1);
+                 if ($1 <= $3)
+                   $$ = (1 << ($3 + 1)) - 1 - ((1 << $1) - 1);
+                 else
+                   $$ = (1 << ($1 + 1)) - 1 - ((1 << $3) - 1);
                }
        ;
 
@@ -637,9 +684,8 @@ static char *strorig;
 /* If *CCP could be a register, return the register number and advance
    *CCP.  Otherwise don't change *CCP, and return 0.  */
 
-enum m68k_register
-m68k_reg_parse (ccp)
-     register char **ccp;
+static enum m68k_register
+m68k_reg_parse (char **ccp)
 {
   char *start = *ccp;
   char c;
@@ -677,19 +723,37 @@ m68k_reg_parse (ccp)
       return S_GET_VALUE (symbolp);
     }
 
+  /* In MRI mode, something like foo.bar can be equated to a register
+     name.  */
+  while (flag_mri && c == '.')
+    {
+      ++p;
+      while (is_part_of_name (*p) && *p != '.' && *p != ':' && *p != '*')
+       p++;
+      c = *p;
+      *p = '\0';
+      symbolp = symbol_find (start);
+      *p = c;
+      if (symbolp != NULL && S_GET_SEGMENT (symbolp) == reg_section)
+       {
+         *ccp = p;
+         return S_GET_VALUE (symbolp);
+       }
+    }
+
   return 0;
 }
 
 /* The lexer.  */
 
 static int
-yylex ()
+yylex (void)
 {
   enum m68k_register reg;
   char *s;
   int parens;
   int c = 0;
-  char *hold;
+  int tail = 0;
 
   if (*str == ' ')
     ++str;
@@ -700,27 +764,38 @@ yylex ()
   /* Various special characters are just returned directly.  */
   switch (*str)
     {
+    case '@':
+      /* In MRI mode, this can be the start of an octal number.  */
+      if (flag_mri)
+       {
+         if (ISDIGIT (str[1])
+             || ((str[1] == '+' || str[1] == '-')
+                 && ISDIGIT (str[2])))
+           break;
+       }
+      /* Fall through.  */
     case '#':
     case '&':
     case ',':
     case ')':
     case '/':
-    case '@':
     case '[':
     case ']':
+    case '<':
+    case '>':
       return *str++;
     case '+':
       /* It so happens that a '+' can only appear at the end of an
-         operand.  If it appears anywhere else, it must be a unary
-         plus on an expression.  */
-      if (str[1] == '\0')
+        operand, or if it is trailed by an '&'(see mac load insn).
+        If it appears anywhere else, it must be a unary.  */
+      if (str[1] == '\0' || (str[1] == '&' && str[2] == '\0'))
        return *str++;
       break;
     case '-':
       /* A '-' can only appear in -(ar), rn-rn, or ar@-.  If it
          appears anywhere else, it must be a unary minus on an
-         expression.  */
-      if (str[1] == '\0')
+         expression, unless it it trailed by a '&'(see mac load insn).  */
+      if (str[1] == '\0' || (str[1] == '&' && str[2] == '\0'))
        return *str++;
       s = str + 1;
       if (*s == '(')
@@ -823,30 +898,41 @@ yylex ()
              ++s;
              break;
            default:
-             yyerror ("illegal size specification");
+             yyerror (_("illegal size specification"));
              yylval.indexreg.size = SIZE_UNSPEC;
              break;
            }
        }
 
-      if (*s != '*' && *s != ':')
-       yylval.indexreg.scale = 1;
-      else
+      yylval.indexreg.scale = 1;
+
+      if (*s == '*' || *s == ':')
        {
+         expressionS scale;
+
          ++s;
-         switch (*s)
+
+         temp_ilp (s);
+         expression (&scale);
+         s = input_line_pointer;
+         restore_ilp ();
+
+         if (scale.X_op != O_constant)
+           yyerror (_("scale specification must resolve to a number"));
+         else
            {
-           case '1':
-           case '2':
-           case '4':
-           case '8':
-             yylval.indexreg.scale = *s - '0';
-             ++s;
-             break;
-           default:
-             yyerror ("illegal scale specification");
-             yylval.indexreg.scale = 1;
-             break;
+             switch (scale.X_add_number)
+               {
+               case 1:
+               case 2:
+               case 4:
+               case 8:
+                 yylval.indexreg.scale = scale.X_add_number;
+                 break;
+               default:
+                 yyerror (_("invalid scale value"));
+                 break;
+               }
            }
        }
 
@@ -869,7 +955,7 @@ yylex ()
        {
          if (parens == 0
              && s > str
-             && (s[-1] == ')' || isalnum ((unsigned char) s[-1])))
+             && (s[-1] == ')' || ISALNUM (s[-1])))
            break;
          ++parens;
        }
@@ -887,7 +973,7 @@ yylex ()
   yylval.exp.size = SIZE_UNSPEC;
   if (s <= str + 2
       || (s[-2] != '.' && s[-2] != ':'))
-    s = NULL;
+    tail = 0;
   else
     {
       switch (s[-1])
@@ -907,25 +993,90 @@ yylex ()
          yylval.exp.size = SIZE_LONG;
          break;
        default:
-         s = NULL;
          break;
        }
       if (yylval.exp.size != SIZE_UNSPEC)
-       {
-         c = s[-2];
-         s[-2] = '\0';
-       }
+       tail = 2;
+    }
+
+#ifdef OBJ_ELF
+  {
+    /* Look for @PLTPC, etc.  */
+    char *cp;
+
+    yylval.exp.pic_reloc = pic_none;
+    cp = s - tail;
+    if (cp - 7 > str && cp[-7] == '@')
+      {
+       if (strncmp (cp - 7, "@TLSLDM", 7) == 0)
+         {
+           yylval.exp.pic_reloc = pic_tls_ldm;
+           tail += 7;
+         }
+       else if (strncmp (cp - 7, "@TLSLDO", 7) == 0)
+         {
+           yylval.exp.pic_reloc = pic_tls_ldo;
+           tail += 7;
+         }
+      }
+    else if (cp - 6 > str && cp[-6] == '@')
+      {
+       if (strncmp (cp - 6, "@PLTPC", 6) == 0)
+         {
+           yylval.exp.pic_reloc = pic_plt_pcrel;
+           tail += 6;
+         }
+       else if (strncmp (cp - 6, "@GOTPC", 6) == 0)
+         {
+           yylval.exp.pic_reloc = pic_got_pcrel;
+           tail += 6;
+         }
+       else if (strncmp (cp - 6, "@TLSGD", 6) == 0)
+         {
+           yylval.exp.pic_reloc = pic_tls_gd;
+           tail += 6;
+         }
+       else if (strncmp (cp - 6, "@TLSIE", 6) == 0)
+         {
+           yylval.exp.pic_reloc = pic_tls_ie;
+           tail += 6;
+         }
+       else if (strncmp (cp - 6, "@TLSLE", 6) == 0)
+         {
+           yylval.exp.pic_reloc = pic_tls_le;
+           tail += 6;
+         }
+      }
+    else if (cp - 4 > str && cp[-4] == '@')
+      {
+       if (strncmp (cp - 4, "@PLT", 4) == 0)
+         {
+           yylval.exp.pic_reloc = pic_plt_off;
+           tail += 4;
+         }
+       else if (strncmp (cp - 4, "@GOT", 4) == 0)
+         {
+           yylval.exp.pic_reloc = pic_got_off;
+           tail += 4;
+         }
+      }
+  }
+#endif
+
+  if (tail != 0)
+    {
+      c = s[-tail];
+      s[-tail] = 0;
     }
 
-  hold = input_line_pointer;
-  input_line_pointer = str;
+  temp_ilp (str);
   expression (&yylval.exp.exp);
   str = input_line_pointer;
-  input_line_pointer = hold;
+  restore_ilp ();
 
-  if (s != NULL)
+  if (tail != 0)
     {
-      s[-2] = c;
+      s[-tail] = c;
       str = s;
     }
 
@@ -936,9 +1087,7 @@ yylex ()
    from outside this file.  */
 
 int
-m68k_ip_op (s, oparg)
-     char *s;
-     struct m68k_op *oparg;
+m68k_ip_op (char *s, struct m68k_op *oparg)
 {
   memset (oparg, 0, sizeof *oparg);
   oparg->error = NULL;
@@ -956,8 +1105,7 @@ m68k_ip_op (s, oparg)
 /* The error handler.  */
 
 static void
-yyerror (s)
-     const char *s;
+yyerror (const char *s)
 {
   op->error = s;
 }
This page took 0.031216 seconds and 4 git commands to generate.