gas: blackfin: reign in overeager insn flag handling
authorMike Frysinger <vapier@gentoo.org>
Mon, 11 Oct 2010 08:37:20 +0000 (08:37 +0000)
committerMike Frysinger <vapier@gentoo.org>
Mon, 11 Oct 2010 08:37:20 +0000 (08:37 +0000)
Currently, trying to declare single letter variables in Blackfin assembly
can sometimes lead to parser errors if that letter is used for insn flags.
For example, X, Z, S, M, and T are used to change the behavior of insns:
    R0 = 1; R0 = 1 (X); R0 = 1 (Z);
But the current parser just looks for single letter tokens rather than
ones that show up in the (FLAGS) field.  So only match these letters as
flags when they're in parentheses.

Not a complete fix, but it at least lets gcc tests pass now (the test
gcc/testsuite/gcc.c-torture/compile/mangle-1.c to be exact).  A complete
fix would require a significant parser rewrite in order to handle:
    R0 = (x) (x);   /* zero extend the address of the symbol "x" */
    R0 = W; R0 = W[P0];

Signed-off-by: Steve Kilbane <steve.kilbane@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
gas/ChangeLog
gas/config/bfin-lex.l

index ef213458ded3161f020211b4a9e9709458f757b6..9d1de5c927c099ebac71e9f26bcc08cef3f24af9 100644 (file)
@@ -1,3 +1,9 @@
+2010-09-11  Steve Kilbane  <steve.kilbane@analog.com>
+
+       * config/bfin-lex.l (FLAGS): New state.
+       (X, Z, S, M, T): Require FLAGS state.
+       ("(", ")"): Start/stop FLAGS state.
+
 2010-09-11  David Gibson  <david.gibson@analog.com>
 
        * config/bfin-aux.h (bfin_loop_attempt_create_label): New prototype.
index bdd02f5bcffc27fcd16302f2cc468286ff82dd43..960600689ece305477b42e2bb5e2abbae7dd264f 100644 (file)
@@ -39,6 +39,7 @@ int yylex (void);
    and <INITIAL> would match some keyword rules only with
    initial.  */
 %s KEYWORD
+%s FLAGS
 
 %%
 [sS][fF][tT][rR][eE][sS][eE][tT]        _REG.regno = REG_sftreset;  return REG;
@@ -47,8 +48,8 @@ int yylex (void);
 [hH][wW][eE][rR][rR][cC][aA][uU][sS][eE] _REG.regno = REG_hwerrcause; return REG;
 [eE][xX][cC][aA][uU][sS][eE]            _REG.regno = REG_excause;   return REG;
 [eE][mM][uU][cC][aA][uU][sS][eE]       _REG.regno = REG_emucause;  return REG;
-[zZ]                                    return Z;
-[xX]                                    return X;
+<FLAGS>[zZ]                             return Z;
+<FLAGS>[xX]                             return X;
 [wW]32                                  yylval.value = M_W32; return MMOD;
 [wW]                                    return W;
 [vV][iI][tT]_[mM][aA][xX]               return VIT_MAX;
@@ -58,8 +59,8 @@ int yylex (void);
 [tT][hH]                                return TH;
 [tT][fF][uU]                            yylval.value = M_TFU; return MMOD;
 [tT][eE][sS][tT][sS][eE][tT]            return TESTSET;
-[tT]                                    yylval.value = M_T; return MMOD;
-[sS]                                                        return S;
+<FLAGS>[tT]                             yylval.value = M_T; return MMOD;
+<FLAGS>[sS]                             return S;
 [sS][yY][sS][cC][fF][gG]       _REG.regno = REG_SYSCFG; return REG;
 [sS][tT][iI]                            return STI;
 [sS][sS][yY][nN][cC]                    return SSYNC;
@@ -122,7 +123,7 @@ int yylex (void);
 [mM][0-3]"."[lLhH]  return parse_halfreg (&yylval.reg, T_REG_M, yytext);
 [mM][0-3]           return parse_reg (&yylval.reg, T_REG_M, yytext);
 
-[mM]                                    return M;
+<FLAGS>[mM]                             return M;
 [lL][tT]                                return LT;
 [lL][sS][hH][iI][fF][tT]                return LSHIFT;
 [lL][sS][eE][tT][uU][pP]                return LSETUP;
@@ -263,8 +264,8 @@ int yylex (void);
 "<<="                   return _LESS_LESS_ASSIGN;
 "<<"                    return LESS_LESS;
 "<"                     return LESS_THAN;
-"("                     return LPAREN;
-")"                     return RPAREN;
+"("                     BEGIN(FLAGS); return LPAREN;
+")"                     BEGIN(INITIAL); return RPAREN;
 ":"                     return COLON;
 "/"                     return SLASH;
 "-="                    return _MINUS_ASSIGN;