X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Fm68k-parse.y;h=8bc96d13d16e68535e3a748fb7bf7ac5debc36fb;hb=0ac2b354ee006d94d6fc46bea08f39f99b18f869;hp=d3d690a858013664e8be05d31c4e605d7d5b025f;hpb=a1c7c0f3ac78467be6f4d649a0ac0a7b2302aa2a;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/m68k-parse.y b/gas/config/m68k-parse.y index d3d690a858..8bc96d13d1 100644 --- a/gas/config/m68k-parse.y +++ b/gas/config/m68k-parse.y @@ -1,12 +1,12 @@ /* m68k.y -- bison grammar for m68k operand parsing - Copyright (C) 1995 Free Software Foundation, Inc. + Copyright (C) 1995-2019 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 @@ -29,12 +29,13 @@ #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 @@ -43,13 +44,13 @@ #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,9 +82,9 @@ /* Internal functions. */ -static enum m68k_register m68k_reg_parse PARAMS ((char **)); -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; @@ -97,6 +98,7 @@ static struct m68k_op *op; struct m68k_exp exp; unsigned long mask; int onereg; + int trailing_ampersand; } %token DR AR FPR FPCR LPC ZAR ZDR LZPC CREG @@ -108,6 +110,7 @@ static struct m68k_op *op; %type optcexpr optexprc %type reglist ireglist reglistpair %type reglistreg +%type optional_ampersand %% @@ -115,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; @@ -200,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; @@ -210,12 +247,17 @@ motorola_operand: else op->mode = DISP; } + | '(' LPC ')' + { + op->mode = DISP; + op->reg = $2; + } | '(' ZAR ')' { op->mode = BASE; op->reg = $2; } - | '(' zpc ')' + | '(' LZPC ')' { op->mode = BASE; op->reg = $2; @@ -230,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; @@ -245,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; @@ -261,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; @@ -272,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; @@ -338,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; @@ -350,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; @@ -375,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; } @@ -383,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; } @@ -391,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; } @@ -592,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); } ; @@ -634,8 +685,7 @@ static char *strorig; *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; @@ -673,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; @@ -696,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 == '(') @@ -819,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; + } } } @@ -865,7 +955,7 @@ yylex () { if (parens == 0 && s > str - && (s[-1] == ')' || isalnum ((unsigned char) s[-1]))) + && (s[-1] == ')' || ISALNUM (s[-1]))) break; ++parens; } @@ -883,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]) @@ -903,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; } @@ -932,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; @@ -952,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; }