Fix formatting.
[deliverable/binutils-gdb.git] / gas / config / m68k-parse.y
index dea1a53865010adcbf0e4366d0a0e827d2ebf126..70a4e4fe86ebc8509883893c252da4e6e53de85d 100644 (file)
@@ -1,5 +1,5 @@
 /* m68k.y -- bison grammar for m68k operand parsing
-   Copyright (C) 1995 Free Software Foundation, Inc.
+   Copyright (C) 1995, 96, 1997, 1998 Free Software Foundation, Inc.
    Written by Ken Raeburn and Ian Lance Taylor, Cygnus Support
 
    This file is part of GAS, the GNU Assembler.
@@ -81,7 +81,8 @@
 
 /* Internal functions.  */
 
-static int yylex PARAMS (());
+static enum m68k_register m68k_reg_parse PARAMS ((char **));
+static int yylex PARAMS ((void));
 static void yyerror PARAMS ((const char *));
 
 /* The parser sets fields pointed to by this global variable.  */
@@ -199,6 +200,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 +245,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 +260,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 +282,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 +293,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 +359,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 +371,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 +396,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 +404,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 +412,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 +613,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,7 +657,7 @@ 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
+static enum m68k_register
 m68k_reg_parse (ccp)
      register char **ccp;
 {
@@ -677,6 +697,24 @@ 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;
 }
 
@@ -689,6 +727,7 @@ yylex ()
   char *s;
   int parens;
   int c = 0;
+  int tail = 0;
   char *hold;
 
   if (*str == ' ')
@@ -700,12 +739,21 @@ 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 ']':
       return *str++;
@@ -823,30 +871,42 @@ 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)
+
+         hold = input_line_pointer;
+         input_line_pointer = s;
+         expression (&scale);
+         s = input_line_pointer;
+         input_line_pointer = hold;
+
+         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;
+               }
            }
        }
 
@@ -887,7 +947,7 @@ yylex ()
   yylval.exp.size = SIZE_UNSPEC;
   if (s <= str + 2
       || (s[-2] != '.' && s[-2] != ':'))
-    s = NULL;
+    tail = 0;
   else
     {
       switch (s[-1])
@@ -907,14 +967,52 @@ 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 - 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 (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;
@@ -923,9 +1021,9 @@ yylex ()
   str = input_line_pointer;
   input_line_pointer = hold;
 
-  if (s != NULL)
+  if (tail != 0)
     {
-      s[-2] = c;
+      s[-tail] = c;
       str = s;
     }
 
This page took 0.029546 seconds and 4 git commands to generate.