/* m68k.y -- bison grammar for m68k operand parsing
- Copyright 1995, 1996, 1997, 1998, 2001 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
- 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,
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
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
#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
/* 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;
struct m68k_exp exp;
unsigned long mask;
int onereg;
+ int trailing_ampersand;
}
%token <reg> DR AR FPR FPCR LPC ZAR ZDR LZPC CREG
%type <exp> optcexpr optexprc
%type <mask> reglist ireglist reglistpair
%type <onereg> reglistreg
+%type <trailing_ampersand> optional_ampersand
%%
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;
*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;
/* The lexer. */
static int
-yylex ()
+yylex (void)
{
enum m68k_register reg;
char *s;
int parens;
int c = 0;
int tail = 0;
- char *hold;
if (*str == ' ')
++str;
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 == '(')
++s;
- hold = input_line_pointer;
- input_line_pointer = s;
+ temp_ilp (s);
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"));
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)
{
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] == '@')
{
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 (tail != 0)
{
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;
/* The error handler. */
static void
-yyerror (s)
- const char *s;
+yyerror (const char *s)
{
op->error = s;
}