/* 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
#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
#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;
}