/* m68k.y -- bison grammar for m68k operand parsing
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright 1995, 1996, 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.
/* 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. */
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;
| '(' EXPR ',' zapc ',' zpc ')'
{
if ($4 == PC || $4 == ZPC)
- yyerror ("syntax error");
+ yyerror (_("syntax error"));
op->mode = BASE;
op->reg = $6;
op->disp = $2;
op->disp = $2;
op->index = $4;
}
+ | '(' zdireg ',' EXPR ')'
+ {
+ op->mode = BASE;
+ op->disp = $4;
+ op->index = $2;
+ }
| EXPR '(' zapc ',' zireg ')'
{
op->mode = BASE;
| EXPR '(' zapc ',' zpc ')'
{
if ($3 == PC || $3 == ZPC)
- yyerror ("syntax error");
+ yyerror (_("syntax error"));
op->mode = BASE;
op->reg = $5;
op->disp = $1;
| '(' zapc ',' zpc ')'
{
if ($2 == PC || $2 == ZPC)
- yyerror ("syntax error");
+ yyerror (_("syntax error"));
op->mode = BASE;
op->reg = $4;
op->index.reg = $2;
| '(' '[' EXPR ',' zapc ',' zpc ']' optcexpr ')'
{
if ($5 == PC || $5 == ZPC)
- yyerror ("syntax error");
+ yyerror (_("syntax error"));
op->mode = PRE;
op->reg = $7;
op->disp = $3;
| '(' '[' zapc ',' zpc ']' optcexpr ')'
{
if ($3 == PC || $3 == ZPC)
- yyerror ("syntax error");
+ yyerror (_("syntax error"));
op->mode = PRE;
op->reg = $5;
op->index.reg = $3;
{
/* 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;
}
{
/* 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;
}
{
/* 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;
}
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);
}
;
/* 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;
{
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;
}
char *s;
int parens;
int c = 0;
+ int tail = 0;
char *hold;
if (*str == ' ')
/* 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++;
++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;
+ }
}
}
yylval.exp.size = SIZE_UNSPEC;
if (s <= str + 2
|| (s[-2] != '.' && s[-2] != ':'))
- s = NULL;
+ tail = 0;
else
{
switch (s[-1])
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;
str = input_line_pointer;
input_line_pointer = hold;
- if (s != NULL)
+ if (tail != 0)
{
- s[-2] = c;
+ s[-tail] = c;
str = s;
}