gas/:
[binutils-gdb.git] / gas / config / bfin-parse.y
index cbb223a860aecb5c471b7419f8236a4af2c9bd1a..6a36863a6dda43f95a90d9f6ee763376fa8796c3 100644 (file)
@@ -264,6 +264,35 @@ check_multiply_halfregs (Macfunc *aa, Macfunc *ab)
 }
 
 
+/* Check mac option.  */
+
+static int
+check_macfunc_option (Macfunc *a, Opt_mode *opt)
+{
+  /* Default option is always valid.  */
+  if (opt->mod == 0)
+    return 0;
+
+  if ((a->op == 3 && a->w == 1 && a->P == 1
+       && opt->mod != M_FU && opt->mod != M_S2RND && opt->mod != M_ISS2)
+      || (a->op == 3 && a->w == 1 && a->P == 0
+         && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_IU
+         && opt->mod != M_T && opt->mod != M_S2RND && opt->mod != M_ISS2
+         && opt->mod != M_IH)
+      || (a->w == 0 && a->P == 0
+         && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_W32)
+      || (a->w == 1 && a->P == 1
+         && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_S2RND
+         && opt->mod != M_ISS2)
+      || (a->w == 1 && a->P == 0
+         && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_IU
+         && opt->mod != M_T && opt->mod != M_TFU && opt->mod != M_S2RND
+         && opt->mod != M_ISS2 && opt->mod != M_IH))
+    return -1;
+
+  return 0;
+}
+
 /* Check (vector) mac funcs and ops.  */
 
 static int
@@ -274,6 +303,11 @@ check_macfuncs (Macfunc *aa, Opt_mode *opa,
   Macfunc mtmp;
   Opt_mode otmp;
 
+  /* The option mode should be put at the end of the second instruction
+     of the vector except M, which should follow MAC1 instruction.  */
+  if (opa->mod != 0)
+    return yyerror ("Bad opt mode");
+
   /* If a0macfunc comes before a1macfunc, swap them.  */
        
   if (aa->n == 0)
@@ -291,16 +325,14 @@ check_macfuncs (Macfunc *aa, Opt_mode *opa,
     {
       if (opb->MM != 0)
        return yyerror ("(M) not allowed with A0MAC");
-      if (opa->mod != 0)
-       return yyerror ("Bad opt mode");
       if (ab->n != 0)
        return yyerror ("Vector AxMACs can't be same");
     }
 
   /*  If both ops are one of 0, 1, or 2, we have multiply_halfregs in both
   assignment_or_macfuncs.  */
-  if (aa->op < 3 && aa->op >=0
-      && ab->op < 3 && ab->op >= 0)
+  if ((aa->op == 0 || aa->op == 1 || aa->op == 2)
+      && (ab->op == 0 || ab->op == 1 || ab->op == 2))
     {
       if (check_multiply_halfregs (aa, ab) < 0)
        return -1;
@@ -330,11 +362,17 @@ check_macfuncs (Macfunc *aa, Opt_mode *opa,
            || (ab->w && !aa->P && IS_H (ab->dst)))
     return yyerror ("High/Low register assignment mismatch");
 
+  /* Make sure mod flags get ORed, too.  */
+  opb->mod |= opa->mod;
+
+  /* Check option.  */
+  if (check_macfunc_option (aa, opb) < 0
+      && check_macfunc_option (ab, opb) < 0)
+    return yyerror ("bad option");
+
   /* Make sure first macfunc has got both P flags ORed.  */
   aa->P |= ab->P;
 
-  /* Make sure mod flags get ORed, too.  */
-  opb->mod |= opa->mod;
   return 0;    
 }
 
@@ -660,6 +698,9 @@ asm_1:
          int w0 = 0, w1 = 0;
          int h00, h10, h01, h11;
 
+         if (check_macfunc_option (&$1, &$2) < 0)
+           return yyerror ("bad option");
+
          if ($1.n == 0)
            {
              if ($2.MM) 
@@ -1432,6 +1473,8 @@ asm_1:
              notethat ("COMPI2opD: dregs += imm7\n");
              $$ = COMPI2OPD (&$1, imm7 ($3), 1);
            }
+         else if ((IS_DREG ($1) || IS_PREG ($1)) && IS_CONST ($3))
+           return yyerror ("Immediate value out of range");
          else
            return yyerror ("Register mismatch");
        }
@@ -1552,23 +1595,23 @@ asm_1:
        }
        | CCREG ASSIGN REG_A _ASSIGN_ASSIGN REG_A
        {
-         if (!REG_SAME ($3, $5))
+         if ($3.regno == REG_A0 && $5.regno == REG_A1)
            {
              notethat ("CCflag: CC = A0 == A1\n");
              $$ = CCFLAG (0, 0, 5, 0, 0);
            }
          else
-           return yyerror ("CC register expected");
+           return yyerror ("AREGs are in bad order or same");
        }
        | CCREG ASSIGN REG_A LESS_THAN REG_A
        {
-         if (!REG_SAME ($3, $5))
+         if ($3.regno == REG_A0 && $5.regno == REG_A1)
            {
              notethat ("CCflag: CC = A0 < A1\n");
              $$ = CCFLAG (0, 0, 6, 0, 0);
            }
          else
-           return yyerror ("Register mismatch");
+           return yyerror ("AREGs are in bad order or same");
        }
        | CCREG ASSIGN REG LESS_THAN REG iu_or_nothing
        {
@@ -1597,7 +1640,9 @@ asm_1:
            {
              notethat ("CCflag: CC = dpregs == dpregs\n");
              $$ = CCFLAG (&$3, $5.regno & CODE_MASK, 0, 0, IS_PREG ($3) ? 1 : 0);
-           } 
+           }
+         else
+           return yyerror ("Compare only of same register class");
        }
        | CCREG ASSIGN REG _ASSIGN_ASSIGN expr
        {
@@ -1611,13 +1656,13 @@ asm_1:
        }
        | CCREG ASSIGN REG_A _LESS_THAN_ASSIGN REG_A
        {
-         if (!REG_SAME ($3, $5))
+         if ($3.regno == REG_A0 && $5.regno == REG_A1)
            {
              notethat ("CCflag: CC = A0 <= A1\n");
              $$ = CCFLAG (0, 0, 7, 0, 0);
            }
          else
-           return yyerror ("CC register expected");
+           return yyerror ("AREGs are in bad order or same");
        }
        | CCREG ASSIGN REG _LESS_THAN_ASSIGN REG iu_or_nothing
        {