diff options
Diffstat (limited to 'binutils-2.17/gas/config/m68k-parse.y')
-rw-r--r-- | binutils-2.17/gas/config/m68k-parse.y | 1091 |
1 files changed, 0 insertions, 1091 deletions
diff --git a/binutils-2.17/gas/config/m68k-parse.y b/binutils-2.17/gas/config/m68k-parse.y deleted file mode 100644 index 2140dda8..00000000 --- a/binutils-2.17/gas/config/m68k-parse.y +++ /dev/null @@ -1,1091 +0,0 @@ -/* m68k.y -- bison grammar for m68k operand parsing - Copyright 1995, 1996, 1997, 1998, 2001, 2003, 2004, 2005 - 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) - any later version. - - GAS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - 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, 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 - variations of it. Using a grammar is probably overkill, but at - least it makes clear exactly what we do support. */ - -%{ - -#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 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. */ - -#define yymaxdepth m68k_maxdepth -#define yyparse m68k_parse -#define yylex m68k_lex -#define yyerror m68k_error -#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 yyexca m68k_exca -#define yyerrflag m68k_errflag -#define yynerrs m68k_nerrs -#define yyps m68k_ps -#define yypv m68k_pv -#define yys m68k_s -#define yy_yys m68k_yys -#define yystate m68k_state -#define yytmp m68k_tmp -#define yyv m68k_v -#define yy_yyv m68k_yyv -#define yyval m68k_val -#define yylloc m68k_lloc -#define yyreds m68k_reds /* With YYDEBUG defined */ -#define yytoks m68k_toks /* With YYDEBUG defined */ -#define yylhs m68k_yylhs -#define yylen m68k_yylen -#define yydefred m68k_yydefred -#define yydgoto m68k_yydgoto -#define yysindex m68k_yysindex -#define yyrindex m68k_yyrindex -#define yygindex m68k_yygindex -#define yytable m68k_yytable -#define yycheck m68k_yycheck - -#ifndef YYDEBUG -#define YYDEBUG 1 -#endif - -/* Internal functions. */ - -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; - -%} - -%union -{ - struct m68k_indexreg indexreg; - enum m68k_register reg; - struct m68k_exp exp; - unsigned long mask; - int onereg; - int trailing_ampersand; -} - -%token <reg> DR AR FPR FPCR LPC ZAR ZDR LZPC CREG -%token <indexreg> INDEXREG -%token <exp> EXPR - -%type <indexreg> zireg zdireg -%type <reg> zadr zdr apc zapc zpc optzapc optczapc -%type <exp> optcexpr optexprc -%type <mask> reglist ireglist reglistpair -%type <onereg> reglistreg -%type <trailing_ampersand> optional_ampersand - -%% - -/* An operand. */ - -operand: - generic_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: - '<' '<' - { - op->mode = LSH; - } - - | '>' '>' - { - op->mode = RSH; - } - - | DR - { - op->mode = DREG; - op->reg = $1; - } - | AR - { - op->mode = AREG; - op->reg = $1; - } - | FPR - { - op->mode = FPREG; - op->reg = $1; - } - | FPCR - { - op->mode = CONTROL; - op->reg = $1; - } - | CREG - { - op->mode = CONTROL; - op->reg = $1; - } - | EXPR - { - op->mode = ABSL; - op->disp = $1; - } - | '#' EXPR - { - op->mode = IMMED; - op->disp = $2; - } - | '&' EXPR - { - op->mode = IMMED; - op->disp = $2; - } - | reglist - { - op->mode = REGLST; - op->mask = $1; - } - ; - -/* An operand in Motorola syntax. This includes MRI syntax as well, - which may or may not be different in that it permits commutativity - of index and base registers, and permits an offset expression to - appear inside or outside of the parentheses. */ - -motorola_operand: - '(' AR ')' - { - op->mode = AINDR; - op->reg = $2; - } - | '(' AR ')' '+' - { - op->mode = AINC; - op->reg = $2; - } - | '-' '(' AR ')' - { - op->mode = ADEC; - op->reg = $3; - } - | '(' EXPR ',' zapc ')' - { - op->reg = $4; - op->disp = $2; - if (($4 >= ZADDR0 && $4 <= ZADDR7) - || $4 == ZPC) - op->mode = BASE; - 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; - op->disp = $1; - if (($3 >= ZADDR0 && $3 <= ZADDR7) - || $3 == ZPC) - op->mode = BASE; - else - op->mode = DISP; - } - | '(' LPC ')' - { - op->mode = DISP; - op->reg = $2; - } - | '(' ZAR ')' - { - op->mode = BASE; - op->reg = $2; - } - | '(' LZPC ')' - { - op->mode = BASE; - op->reg = $2; - } - | '(' EXPR ',' zapc ',' zireg ')' - { - op->mode = BASE; - op->reg = $4; - op->disp = $2; - op->index = $6; - } - | '(' EXPR ',' zapc ',' zpc ')' - { - if ($4 == PC || $4 == ZPC) - yyerror (_("syntax error")); - op->mode = BASE; - op->reg = $6; - op->disp = $2; - op->index.reg = $4; - op->index.size = SIZE_UNSPEC; - op->index.scale = 1; - } - | '(' EXPR ',' zdireg optczapc ')' - { - op->mode = BASE; - op->reg = $5; - op->disp = $2; - op->index = $4; - } - | '(' zdireg ',' EXPR ')' - { - op->mode = BASE; - op->disp = $4; - op->index = $2; - } - | EXPR '(' zapc ',' zireg ')' - { - op->mode = BASE; - op->reg = $3; - op->disp = $1; - op->index = $5; - } - | '(' zapc ',' zireg ')' - { - op->mode = BASE; - op->reg = $2; - op->index = $4; - } - | EXPR '(' zapc ',' zpc ')' - { - if ($3 == PC || $3 == ZPC) - yyerror (_("syntax error")); - op->mode = BASE; - op->reg = $5; - op->disp = $1; - op->index.reg = $3; - op->index.size = SIZE_UNSPEC; - op->index.scale = 1; - } - | '(' zapc ',' zpc ')' - { - if ($2 == PC || $2 == ZPC) - yyerror (_("syntax error")); - op->mode = BASE; - op->reg = $4; - op->index.reg = $2; - op->index.size = SIZE_UNSPEC; - op->index.scale = 1; - } - | EXPR '(' zdireg optczapc ')' - { - op->mode = BASE; - op->reg = $4; - op->disp = $1; - op->index = $3; - } - | '(' zdireg optczapc ')' - { - op->mode = BASE; - op->reg = $3; - op->index = $2; - } - | '(' '[' EXPR optczapc ']' ',' zireg optcexpr ')' - { - op->mode = POST; - op->reg = $4; - op->disp = $3; - op->index = $7; - op->odisp = $8; - } - | '(' '[' EXPR optczapc ']' optcexpr ')' - { - op->mode = POST; - op->reg = $4; - op->disp = $3; - op->odisp = $6; - } - | '(' '[' zapc ']' ',' zireg optcexpr ')' - { - op->mode = POST; - op->reg = $3; - op->index = $6; - op->odisp = $7; - } - | '(' '[' zapc ']' optcexpr ')' - { - op->mode = POST; - op->reg = $3; - op->odisp = $5; - } - | '(' '[' EXPR ',' zapc ',' zireg ']' optcexpr ')' - { - op->mode = PRE; - op->reg = $5; - op->disp = $3; - op->index = $7; - op->odisp = $9; - } - | '(' '[' zapc ',' zireg ']' optcexpr ')' - { - op->mode = PRE; - op->reg = $3; - op->index = $5; - op->odisp = $7; - } - | '(' '[' EXPR ',' zapc ',' zpc ']' optcexpr ')' - { - if ($5 == PC || $5 == ZPC) - yyerror (_("syntax error")); - op->mode = PRE; - op->reg = $7; - op->disp = $3; - op->index.reg = $5; - op->index.size = SIZE_UNSPEC; - op->index.scale = 1; - op->odisp = $9; - } - | '(' '[' zapc ',' zpc ']' optcexpr ')' - { - if ($3 == PC || $3 == ZPC) - yyerror (_("syntax error")); - op->mode = PRE; - op->reg = $5; - op->index.reg = $3; - op->index.size = SIZE_UNSPEC; - op->index.scale = 1; - op->odisp = $7; - } - | '(' '[' optexprc zdireg optczapc ']' optcexpr ')' - { - op->mode = PRE; - op->reg = $5; - op->disp = $3; - op->index = $4; - op->odisp = $7; - } - ; - -/* An operand in MIT syntax. */ - -mit_operand: - optzapc '@' - { - /* We use optzapc to avoid a shift/reduce conflict. */ - if ($1 < ADDR0 || $1 > ADDR7) - yyerror (_("syntax error")); - op->mode = AINDR; - op->reg = $1; - } - | optzapc '@' '+' - { - /* We use optzapc to avoid a shift/reduce conflict. */ - if ($1 < ADDR0 || $1 > ADDR7) - yyerror (_("syntax error")); - op->mode = AINC; - op->reg = $1; - } - | optzapc '@' '-' - { - /* We use optzapc to avoid a shift/reduce conflict. */ - if ($1 < ADDR0 || $1 > ADDR7) - yyerror (_("syntax error")); - op->mode = ADEC; - op->reg = $1; - } - | optzapc '@' '(' EXPR ')' - { - op->reg = $1; - op->disp = $4; - if (($1 >= ZADDR0 && $1 <= ZADDR7) - || $1 == ZPC) - op->mode = BASE; - else - op->mode = DISP; - } - | optzapc '@' '(' optexprc zireg ')' - { - op->mode = BASE; - op->reg = $1; - op->disp = $4; - op->index = $5; - } - | optzapc '@' '(' EXPR ')' '@' '(' optexprc zireg ')' - { - op->mode = POST; - op->reg = $1; - op->disp = $4; - op->index = $9; - op->odisp = $8; - } - | optzapc '@' '(' EXPR ')' '@' '(' EXPR ')' - { - op->mode = POST; - op->reg = $1; - op->disp = $4; - op->odisp = $8; - } - | optzapc '@' '(' optexprc zireg ')' '@' '(' EXPR ')' - { - op->mode = PRE; - op->reg = $1; - op->disp = $4; - op->index = $5; - op->odisp = $9; - } - ; - -/* An index register, possibly suppressed, which need not have a size - or scale. */ - -zireg: - INDEXREG - | zadr - { - $$.reg = $1; - $$.size = SIZE_UNSPEC; - $$.scale = 1; - } - ; - -/* A register which may be an index register, but which may not be an - address register. This nonterminal is used to avoid ambiguity when - trying to parse something like (0,d5,a6) as compared to (0,a6,d5). */ - -zdireg: - INDEXREG - | zdr - { - $$.reg = $1; - $$.size = SIZE_UNSPEC; - $$.scale = 1; - } - ; - -/* An address or data register, or a suppressed address or data - register. */ - -zadr: - zdr - | AR - | ZAR - ; - -/* A data register which may be suppressed. */ - -zdr: - DR - | ZDR - ; - -/* Either an address register or the PC. */ - -apc: - AR - | LPC - ; - -/* Either an address register, or the PC, or a suppressed address - register, or a suppressed PC. */ - -zapc: - apc - | LZPC - | ZAR - ; - -/* An optional zapc. */ - -optzapc: - /* empty */ - { - $$ = ZADDR0; - } - | zapc - ; - -/* The PC, optionally suppressed. */ - -zpc: - LPC - | LZPC - ; - -/* ',' zapc when it may be omitted. */ - -optczapc: - /* empty */ - { - $$ = ZADDR0; - } - | ',' zapc - { - $$ = $2; - } - ; - -/* ',' EXPR when it may be omitted. */ - -optcexpr: - /* empty */ - { - $$.exp.X_op = O_absent; - $$.size = SIZE_UNSPEC; - } - | ',' EXPR - { - $$ = $2; - } - ; - -/* EXPR ',' when it may be omitted. */ - -optexprc: - /* empty */ - { - $$.exp.X_op = O_absent; - $$.size = SIZE_UNSPEC; - } - | EXPR ',' - { - $$ = $1; - } - ; - -/* A register list for the movem instruction. */ - -reglist: - reglistpair - | reglistpair '/' ireglist - { - $$ = $1 | $3; - } - | reglistreg '/' ireglist - { - $$ = (1 << $1) | $3; - } - ; - -/* We use ireglist when we know we are looking at a reglist, and we - can safely reduce a simple register to reglistreg. If we permitted - reglist to reduce to reglistreg, it would be ambiguous whether a - plain register were a DREG/AREG/FPREG or a REGLST. */ - -ireglist: - reglistreg - { - $$ = 1 << $1; - } - | reglistpair - | reglistpair '/' ireglist - { - $$ = $1 | $3; - } - | reglistreg '/' ireglist - { - $$ = (1 << $1) | $3; - } - ; - -reglistpair: - reglistreg '-' reglistreg - { - if ($1 <= $3) - $$ = (1 << ($3 + 1)) - 1 - ((1 << $1) - 1); - else - $$ = (1 << ($1 + 1)) - 1 - ((1 << $3) - 1); - } - ; - -reglistreg: - DR - { - $$ = $1 - DATA0; - } - | AR - { - $$ = $1 - ADDR0 + 8; - } - | FPR - { - $$ = $1 - FP0 + 16; - } - | FPCR - { - if ($1 == FPI) - $$ = 24; - else if ($1 == FPS) - $$ = 25; - else - $$ = 26; - } - ; - -%% - -/* The string to parse is stored here, and modified by yylex. */ - -static char *str; - -/* The original string pointer. */ - -static char *strorig; - -/* If *CCP could be a register, return the register number and advance - *CCP. Otherwise don't change *CCP, and return 0. */ - -static enum m68k_register -m68k_reg_parse (ccp) - register char **ccp; -{ - char *start = *ccp; - char c; - char *p; - symbolS *symbolp; - - if (flag_reg_prefix_optional) - { - if (*start == REGISTER_PREFIX) - start++; - p = start; - } - else - { - if (*start != REGISTER_PREFIX) - return 0; - p = start + 1; - } - - if (! is_name_beginner (*p)) - return 0; - - 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); - } - - /* 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 () -{ - enum m68k_register reg; - char *s; - int parens; - int c = 0; - int tail = 0; - char *hold; - - if (*str == ' ') - ++str; - - if (*str == '\0') - return 0; - - /* 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 '>': - return *str++; - case '+': - /* It so happens that a '+' can only appear at the end of an - 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, 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 == '(') - ++s; - if (m68k_reg_parse (&s) != 0) - return *str++; - break; - case '(': - /* A '(' can only appear in `(reg)', `(expr,...', `([', `@(', or - `)('. If it appears anywhere else, it must be starting an - expression. */ - if (str[1] == '[' - || (str > strorig - && (str[-1] == '@' - || str[-1] == ')'))) - return *str++; - s = str + 1; - if (m68k_reg_parse (&s) != 0) - return *str++; - /* Check for the case of '(expr,...' by scanning ahead. If we - find a comma outside of balanced parentheses, we return '('. - If we find an unbalanced right parenthesis, then presumably - the '(' really starts an expression. */ - parens = 0; - for (s = str + 1; *s != '\0'; s++) - { - if (*s == '(') - ++parens; - else if (*s == ')') - { - if (parens == 0) - break; - --parens; - } - else if (*s == ',' && parens == 0) - { - /* A comma can not normally appear in an expression, so - this is a case of '(expr,...'. */ - return *str++; - } - } - } - - /* See if it's a register. */ - - reg = m68k_reg_parse (&str); - if (reg != 0) - { - int ret; - - yylval.reg = reg; - - if (reg >= DATA0 && reg <= DATA7) - ret = DR; - else if (reg >= ADDR0 && reg <= ADDR7) - ret = AR; - else if (reg >= FP0 && reg <= FP7) - return FPR; - else if (reg == FPI - || reg == FPS - || reg == FPC) - return FPCR; - else if (reg == PC) - return LPC; - else if (reg >= ZDATA0 && reg <= ZDATA7) - ret = ZDR; - else if (reg >= ZADDR0 && reg <= ZADDR7) - ret = ZAR; - else if (reg == ZPC) - return LZPC; - else - return CREG; - - /* If we get here, we have a data or address register. We - must check for a size or scale; if we find one, we must - return INDEXREG. */ - - s = str; - - if (*s != '.' && *s != ':' && *s != '*') - return ret; - - yylval.indexreg.reg = reg; - - if (*s != '.' && *s != ':') - yylval.indexreg.size = SIZE_UNSPEC; - else - { - ++s; - switch (*s) - { - case 'w': - case 'W': - yylval.indexreg.size = SIZE_WORD; - ++s; - break; - case 'l': - case 'L': - yylval.indexreg.size = SIZE_LONG; - ++s; - break; - default: - yyerror (_("illegal size specification")); - yylval.indexreg.size = SIZE_UNSPEC; - break; - } - } - - yylval.indexreg.scale = 1; - - if (*s == '*' || *s == ':') - { - expressionS scale; - - ++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 - { - 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; - } - } - } - - str = s; - - return INDEXREG; - } - - /* It must be an expression. Before we call expression, we need to - look ahead to see if there is a size specification. We must do - that first, because otherwise foo.l will be treated as the symbol - foo.l, rather than as the symbol foo with a long size - specification. The grammar requires that all expressions end at - the end of the operand, or with ',', '(', ']', ')'. */ - - parens = 0; - for (s = str; *s != '\0'; s++) - { - if (*s == '(') - { - if (parens == 0 - && s > str - && (s[-1] == ')' || ISALNUM (s[-1]))) - break; - ++parens; - } - else if (*s == ')') - { - if (parens == 0) - break; - --parens; - } - else if (parens == 0 - && (*s == ',' || *s == ']')) - break; - } - - yylval.exp.size = SIZE_UNSPEC; - if (s <= str + 2 - || (s[-2] != '.' && s[-2] != ':')) - tail = 0; - else - { - switch (s[-1]) - { - case 's': - case 'S': - case 'b': - case 'B': - yylval.exp.size = SIZE_BYTE; - break; - case 'w': - case 'W': - yylval.exp.size = SIZE_WORD; - break; - case 'l': - case 'L': - yylval.exp.size = SIZE_LONG; - break; - default: - break; - } - if (yylval.exp.size != SIZE_UNSPEC) - 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; - input_line_pointer = str; - expression (&yylval.exp.exp); - str = input_line_pointer; - input_line_pointer = hold; - - if (tail != 0) - { - s[-tail] = c; - str = s; - } - - return EXPR; -} - -/* Parse an m68k operand. This is the only function which is called - from outside this file. */ - -int -m68k_ip_op (s, oparg) - char *s; - struct m68k_op *oparg; -{ - memset (oparg, 0, sizeof *oparg); - oparg->error = NULL; - oparg->index.reg = ZDATA0; - oparg->index.scale = 1; - oparg->disp.exp.X_op = O_absent; - oparg->odisp.exp.X_op = O_absent; - - str = strorig = s; - op = oparg; - - return yyparse (); -} - -/* The error handler. */ - -static void -yyerror (s) - const char *s; -{ - op->error = s; -} |