gas: Fix checking for backwards .org with negative offset
[deliverable/binutils-gdb.git] / gas / config / m68k-parse.y
index 70a4e4fe86ebc8509883893c252da4e6e53de85d..11874298c0f4b6aaf203578e3d712ba42901ff13 100644 (file)
@@ -1,12 +1,12 @@
 /* m68k.y -- bison grammar for m68k operand parsing
 /* m68k.y -- bison grammar for m68k operand parsing
-   Copyright (C) 1995, 96, 1997, 1998 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
    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,
    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
 
    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
 
 /* 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 "as.h"
 #include "tc-m68k.h"
 #include "m68k-parse.h"
+#include "safe-ctype.h"
 
 /* Remap normal yacc parser interface names (yyparse, yylex, yyerror,
 
 /* 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
    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        yymaxdepth m68k_maxdepth
 #define        yyparse m68k_parse
 #define        yylval  m68k_lval
 #define        yychar  m68k_char
 #define        yydebug m68k_debug
 #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
 #define        yyexca  m68k_exca
 #define yyerrflag m68k_errflag
 #define yynerrs        m68k_nerrs
@@ -81,9 +82,9 @@
 
 /* Internal functions.  */
 
 
 /* Internal functions.  */
 
-static enum m68k_register m68k_reg_parse PARAMS ((char **));
-static int yylex PARAMS ((void));
-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;
 
 /* The parser sets fields pointed to by this global variable.  */
 static struct m68k_op *op;
@@ -97,6 +98,7 @@ static struct m68k_op *op;
   struct m68k_exp exp;
   unsigned long mask;
   int onereg;
   struct m68k_exp exp;
   unsigned long mask;
   int onereg;
+  int trailing_ampersand;
 }
 
 %token <reg> DR AR FPR FPCR LPC ZAR ZDR LZPC CREG
 }
 
 %token <reg> DR AR FPR FPCR LPC ZAR ZDR LZPC CREG
@@ -108,6 +110,7 @@ static struct m68k_op *op;
 %type <exp> optcexpr optexprc
 %type <mask> reglist ireglist reglistpair
 %type <onereg> reglistreg
 %type <exp> optcexpr optexprc
 %type <mask> reglist ireglist reglistpair
 %type <onereg> reglistreg
+%type <trailing_ampersand> optional_ampersand
 
 %%
 
 
 %%
 
@@ -115,14 +118,38 @@ static struct m68k_op *op;
 
 operand:
          generic_operand
 
 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:
        ;
 
 /* A generic operand.  */
 
 generic_operand:
-         DR
+         '<' '<'
+               {
+                 op->mode = LSH;
+               }
+
+       | '>' '>'
+               {
+                 op->mode = RSH;
+               }
+
+       | DR
                {
                  op->mode = DREG;
                  op->reg = $1;
                {
                  op->mode = DREG;
                  op->reg = $1;
@@ -658,8 +685,7 @@ static char *strorig;
    *CCP.  Otherwise don't change *CCP, and return 0.  */
 
 static enum m68k_register
    *CCP.  Otherwise don't change *CCP, and return 0.  */
 
 static enum m68k_register
-m68k_reg_parse (ccp)
-     register char **ccp;
+m68k_reg_parse (char **ccp)
 {
   char *start = *ccp;
   char c;
 {
   char *start = *ccp;
   char c;
@@ -721,14 +747,13 @@ m68k_reg_parse (ccp)
 /* The lexer.  */
 
 static int
 /* The lexer.  */
 
 static int
-yylex ()
+yylex (void)
 {
   enum m68k_register reg;
   char *s;
   int parens;
   int c = 0;
   int tail = 0;
 {
   enum m68k_register reg;
   char *s;
   int parens;
   int c = 0;
   int tail = 0;
-  char *hold;
 
   if (*str == ' ')
     ++str;
 
   if (*str == ' ')
     ++str;
@@ -743,9 +768,9 @@ yylex ()
       /* In MRI mode, this can be the start of an octal number.  */
       if (flag_mri)
        {
       /* In MRI mode, this can be the start of an octal number.  */
       if (flag_mri)
        {
-         if (isdigit (str[1])
+         if (ISDIGIT (str[1])
              || ((str[1] == '+' || str[1] == '-')
              || ((str[1] == '+' || str[1] == '-')
-                 && isdigit (str[2])))
+                 && ISDIGIT (str[2])))
            break;
        }
       /* Fall through.  */
            break;
        }
       /* Fall through.  */
@@ -756,19 +781,21 @@ yylex ()
     case '/':
     case '[':
     case ']':
     case '/':
     case '[':
     case ']':
+    case '<':
+    case '>':
       return *str++;
     case '+':
       /* It so happens that a '+' can only appear at the end of an
       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
        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 == '(')
        return *str++;
       s = str + 1;
       if (*s == '(')
@@ -885,11 +912,10 @@ yylex ()
 
          ++s;
 
 
          ++s;
 
-         hold = input_line_pointer;
-         input_line_pointer = s;
+         temp_ilp (s);
          expression (&scale);
          s = input_line_pointer;
          expression (&scale);
          s = input_line_pointer;
-         input_line_pointer = hold;
+         restore_ilp ();
 
          if (scale.X_op != O_constant)
            yyerror (_("scale specification must resolve to a number"));
 
          if (scale.X_op != O_constant)
            yyerror (_("scale specification must resolve to a number"));
@@ -929,7 +955,7 @@ yylex ()
        {
          if (parens == 0
              && s > str
        {
          if (parens == 0
              && s > str
-             && (s[-1] == ')' || isalnum ((unsigned char) s[-1])))
+             && (s[-1] == ')' || ISALNUM (s[-1])))
            break;
          ++parens;
        }
            break;
          ++parens;
        }
@@ -980,7 +1006,20 @@ yylex ()
 
     yylval.exp.pic_reloc = pic_none;
     cp = s - tail;
 
     yylval.exp.pic_reloc = pic_none;
     cp = s - tail;
-    if (cp - 6 > str && cp[-6] == '@')
+    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)
          {
       {
        if (strncmp (cp - 6, "@PLTPC", 6) == 0)
          {
@@ -992,6 +1031,21 @@ yylex ()
            yylval.exp.pic_reloc = pic_got_pcrel;
            tail += 6;
          }
            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] == '@')
       {
       }
     else if (cp - 4 > str && cp[-4] == '@')
       {
@@ -1015,11 +1069,10 @@ yylex ()
       s[-tail] = 0;
     }
 
       s[-tail] = 0;
     }
 
-  hold = input_line_pointer;
-  input_line_pointer = str;
+  temp_ilp (str);
   expression (&yylval.exp.exp);
   str = input_line_pointer;
   expression (&yylval.exp.exp);
   str = input_line_pointer;
-  input_line_pointer = hold;
+  restore_ilp ();
 
   if (tail != 0)
     {
 
   if (tail != 0)
     {
@@ -1034,9 +1087,7 @@ yylex ()
    from outside this file.  */
 
 int
    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;
 {
   memset (oparg, 0, sizeof *oparg);
   oparg->error = NULL;
@@ -1054,8 +1105,7 @@ m68k_ip_op (s, oparg)
 /* The error handler.  */
 
 static void
 /* The error handler.  */
 
 static void
-yyerror (s)
-     const char *s;
+yyerror (const char *s)
 {
   op->error = s;
 }
 {
   op->error = s;
 }
This page took 0.028557 seconds and 4 git commands to generate.