* s390-opc.c (INSTR_SS_L2RDRD): New.
[deliverable/binutils-gdb.git] / gas / config / bfin-parse.y
index 38c3f6e684c7e2c42a82da4b62c4b4904e3d80cc..b3416aa1130a7a7e2aedb71256843070cc1a664a 100644 (file)
@@ -1,5 +1,5 @@
 /* bfin-parse.y  ADI Blackfin parser
-   Copyright 2005
+   Copyright 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
    02110-1301, USA.  */
 %{
 
-#include <stdio.h>
-#include "bfin-aux.h"
-#include <stdarg.h>
+#include "as.h"
 #include <obstack.h>
 
+#include "bfin-aux.h"  // opcode generating auxiliaries
+#include "libbfd.h"
+#include "elf/common.h"
+#include "elf/bfin.h"
+
 #define DSP32ALU(aopcde, HL, dst1, dst0, src0, src1, s, x, aop) \
        bfin_gen_dsp32alu (HL, aopcde, aop, s, x, dst0, dst1, src0, src1)
 
@@ -294,9 +297,10 @@ check_macfuncs (Macfunc *aa, Opt_mode *opa,
        return yyerror ("Vector AxMACs can't be same");
     }
 
-  /*  If both ops are != 3, we have multiply_halfregs in both
+  /*  If both ops are one of 0, 1, or 2, we have multiply_halfregs in both
   assignment_or_macfuncs.  */
-  if (aa->op == ab->op && aa->op != 3)
+  if (aa->op < 3 && aa->op >=0
+      && ab->op < 3 && ab->op >= 0)
     {
       if (check_multiply_halfregs (aa, ab) < 0)
        return -1;
@@ -485,7 +489,8 @@ is_group2 (INSTR_T x)
 %token STATUS_REG
 %token MNOP
 %token SYMBOL NUMBER
-%token GOT AT PLTPC
+%token GOT GOT17M4 FUNCDESC_GOT17M4
+%token AT PLTPC
 
 /* Types.  */
 %type <instr> asm
@@ -544,7 +549,7 @@ is_group2 (INSTR_T x)
 %type <expr> got
 %type <expr> got_or_expr
 %type <expr> pltpc
-
+%type <value> any_gotrel GOT GOT17M4 FUNCDESC_GOT17M4
 
 /* Precedence rules.  */
 %left BAR
@@ -1221,24 +1226,21 @@ asm_1:
              /* 7 bit immediate value if possible.
                 We will check for that constant value for efficiency
                 If it goes to reloc, it will be 16 bit.  */
-             if (IS_CONST ($3) && IS_IMM ($3, 7) && (IS_DREG ($1) || IS_PREG ($1)))
+             if (IS_CONST ($3) && IS_IMM ($3, 7) && IS_DREG ($1))
+               {
+                 notethat ("COMPI2opD: dregs = imm7 (x) \n");
+                 $$ = COMPI2OPD (&$1, imm7 ($3), 0);
+               }
+             else if (IS_CONST ($3) && IS_IMM ($3, 7) && IS_PREG ($1))
                {
-                 /* if the expr is a relocation, generate it.  */
-                 if (IS_DREG ($1) && IS_IMM ($3, 7))
-                   {
-                     notethat ("COMPI2opD: dregs = imm7 (x) \n");
-                     $$ = COMPI2OPD (&$1, imm7 ($3), 0);
-                   }
-                 else if (IS_PREG ($1) && IS_IMM ($3, 7))
-                   {
-                     notethat ("COMPI2opP: pregs = imm7 (x)\n");
-                     $$ = COMPI2OPP (&$1, imm7 ($3), 0);
-                   }
-                 else
-                   return yyerror ("Bad register or value for assigment");
+                 notethat ("COMPI2opP: pregs = imm7 (x)\n");
+                 $$ = COMPI2OPP (&$1, imm7 ($3), 0);
                }
              else
                {
+                 if (IS_CONST ($3) && !IS_IMM ($3, 16))
+                   return yyerror ("Immediate value out of range");
+
                  notethat ("LDIMMhalf: regs = luimm16 (x)\n");
                  /* reg, H, S, Z.   */
                  $$ = LDIMMHALF_R5 (&$1, 0, 1, 0, $3);
@@ -1248,6 +1250,10 @@ asm_1:
            {
              /* (z) There is no 7 bit zero extended instruction.
              If the expr is a relocation, generate it.   */
+
+             if (IS_CONST ($3) && !IS_UIMM ($3, 16))
+               return yyerror ("Immediate value out of range");
+
              notethat ("LDIMMhalf: regs = luimm16 (x)\n");
              /* reg, H, S, Z.  */
              $$ = LDIMMHALF_R5 (&$1, 0, 0, 1, $3);
@@ -1724,7 +1730,7 @@ asm_1:
              $$ = DSP32MULT (0, 0, $4.mod, 0, 0,
                              0, 0, IS_H ($3.s0), IS_H ($3.s1), 
                              &$1, 0, &$3.s0, &$3.s1, 1);
-               }       
+           }
        }
 
        | REG ASSIGN multiply_halfregs opt_mode 
@@ -1733,6 +1739,9 @@ asm_1:
          if (!IS_DREG ($1))
            return yyerror ("Dreg expected");
 
+         if (IS_EVEN ($1) && $4.MM)
+           return yyerror ("(M) not allowed with MAC0");
+
          if (!IS_EVEN ($1))
            {
              notethat ("dsp32mult: dregs = multiply_halfregs (opt_mode)\n");
@@ -1741,15 +1750,13 @@ asm_1:
                              IS_H ($3.s0), IS_H ($3.s1), 0, 0,
                              &$1, 0, &$3.s0, &$3.s1, 0);
            }
-         else if ($4.MM == 0)
+         else
            {
              notethat ("dsp32mult: dregs = multiply_halfregs opt_mode\n");
              $$ = DSP32MULT (0, 0, $4.mod, 0, 1,
                              0, 0, IS_H ($3.s0), IS_H ($3.s1), 
                              &$1,  0, &$3.s0, &$3.s1, 1);
            }
-         else
-           return yyerror ("Register or mode mismatch");
        }
 
        | HALF_REG ASSIGN multiply_halfregs opt_mode COMMA
@@ -1758,57 +1765,56 @@ asm_1:
          if (!IS_DREG ($1) || !IS_DREG ($6)) 
            return yyerror ("Dregs expected");
 
+         if (!IS_HCOMPL($1, $6))
+           return yyerror ("Dest registers mismatch");
+
          if (check_multiply_halfregs (&$3, &$8) < 0)
            return -1;
 
-         if (IS_H ($1) && !IS_H ($6))
-           {
-             notethat ("dsp32mult: dregs_hi = multiply_halfregs mxd_mod, "
-                      "dregs_lo = multiply_halfregs opt_mode\n");
-             $$ = DSP32MULT (0, $4.MM, $9.mod, 1, 0,
-                             IS_H ($3.s0), IS_H ($3.s1), IS_H ($8.s0), IS_H ($8.s1),
-                             &$1, 0, &$3.s0, &$3.s1, 1);
-           }
-         else if (!IS_H ($1) && IS_H ($6) && $4.MM == 0)
-           {
-             $$ = DSP32MULT (0, $9.MM, $9.mod, 1, 0,
-                             IS_H ($8.s0), IS_H ($8.s1), IS_H ($3.s0), IS_H ($3.s1),
-                             &$1, 0, &$3.s0, &$3.s1, 1);
-           }
+         if ((!IS_H ($1) && $4.MM)
+             || (!IS_H ($6) && $9.MM))
+           return yyerror ("(M) not allowed with MAC0");
+
+         notethat ("dsp32mult: dregs_hi = multiply_halfregs mxd_mod, "
+                   "dregs_lo = multiply_halfregs opt_mode\n");
+
+         if (IS_H ($1))
+           $$ = DSP32MULT (0, $4.MM, $9.mod, 1, 0,
+                           IS_H ($3.s0), IS_H ($3.s1), IS_H ($8.s0), IS_H ($8.s1),
+                           &$1, 0, &$3.s0, &$3.s1, 1);
          else
-           return yyerror ("Multfunc Register or mode mismatch");
+           $$ = DSP32MULT (0, $9.MM, $9.mod, 1, 0,
+                           IS_H ($8.s0), IS_H ($8.s1), IS_H ($3.s0), IS_H ($3.s1),
+                           &$1, 0, &$3.s0, &$3.s1, 1);
        }
 
-       | REG ASSIGN multiply_halfregs opt_mode COMMA REG ASSIGN multiply_halfregs opt_mode 
+       | REG ASSIGN multiply_halfregs opt_mode COMMA REG ASSIGN multiply_halfregs opt_mode
        {
          if (!IS_DREG ($1) || !IS_DREG ($6)) 
            return yyerror ("Dregs expected");
 
+         if ((IS_EVEN ($1) && $6.regno - $1.regno != 1)
+             || (IS_EVEN ($6) && $1.regno - $6.regno != 1))
+           return yyerror ("Dest registers mismatch");
+
          if (check_multiply_halfregs (&$3, &$8) < 0)
            return -1;
 
+         if ((IS_EVEN ($1) && $4.MM)
+             || (IS_EVEN ($6) && $9.MM))
+           return yyerror ("(M) not allowed with MAC0");
+
          notethat ("dsp32mult: dregs = multiply_halfregs mxd_mod, "
                   "dregs = multiply_halfregs opt_mode\n");
-         if (IS_EVEN ($1))
-           {
-             if ($6.regno - $1.regno != 1 || $4.MM != 0)
-               return yyerror ("Dest registers or mode mismatch");
 
-             /*   op1       MM      mmod  */
-             $$ = DSP32MULT (0, 0, $9.mod, 1, 1,
-                             IS_H ($8.s0), IS_H ($8.s1), IS_H ($3.s0), IS_H ($3.s1),
-                             &$1, 0, &$3.s0, &$3.s1, 1);
-             
-           }
+         if (IS_EVEN ($1))
+           $$ = DSP32MULT (0, $9.MM, $9.mod, 1, 1,
+                           IS_H ($8.s0), IS_H ($8.s1), IS_H ($3.s0), IS_H ($3.s1),
+                           &$1, 0, &$3.s0, &$3.s1, 1);
          else
-           {
-             if ($1.regno - $6.regno != 1)
-               return yyerror ("Dest registers mismatch");
-             
-             $$ = DSP32MULT (0, $9.MM, $9.mod, 1, 1,
-                             IS_H ($3.s0), IS_H ($3.s1), IS_H ($8.s0), IS_H ($8.s1),
-                             &$1, 0, &$3.s0, &$3.s1, 1);
-           }
+           $$ = DSP32MULT (0, $4.MM, $9.mod, 1, 1,
+                           IS_H ($3.s0), IS_H ($3.s1), IS_H ($8.s0), IS_H ($8.s1),
+                           &$1, 0, &$3.s0, &$3.s1, 1);
        }
 
 \f
@@ -3217,16 +3223,6 @@ asm_1:
        }
 
 
-
-/* Expression Assignment.  */
-
-       | expr ASSIGN expr
-       {
-         bfin_equals ($1);
-         $$ = 0;
-       }
-
-
 /*  PushPopMultiple.  */
        | reg_with_predec ASSIGN LPAREN REG COLON expr COMMA REG COLON expr RPAREN
        {
@@ -4110,9 +4106,20 @@ symbol: SYMBOL
        }
        ;
 
-got:   symbol AT GOT
+any_gotrel:
+       GOT
+       { $$ = BFD_RELOC_BFIN_GOT; }
+       | GOT17M4
+       { $$ = BFD_RELOC_BFIN_GOT17M4; }
+       | FUNCDESC_GOT17M4
+       { $$ = BFD_RELOC_BFIN_FUNCDESC_GOT17M4; }
+       ;
+
+got:   symbol AT any_gotrel
        {
-       $$ = $1;
+       Expr_Node_Value val;
+       val.i_value = $3;
+       $$ = Expr_Node_Create (Expr_Node_GOT_Reloc, val, $1, NULL);
        }
        ;
 
@@ -4263,6 +4270,8 @@ value_match (Expr_Node *expr, int sz, int sign, int mul, int issigned)
 static Expr_Node *
 binary (Expr_Op_Type op, Expr_Node *x, Expr_Node *y)
 {
+  Expr_Node_Value val;
+
   if (x->type == Expr_Node_Constant && y->type == Expr_Node_Constant)
     {
       switch (op)
@@ -4312,13 +4321,32 @@ binary (Expr_Op_Type op, Expr_Node *x, Expr_Node *y)
        }
       return x;
     }
-  else
+  /* Canonicalize order to EXPR OP CONSTANT.  */
+  if (x->type == Expr_Node_Constant)
+    {
+      Expr_Node *t = x;
+      x = y;
+      y = t;
+    }
+  /* Canonicalize subtraction of const to addition of negated const.  */
+  if (op == Expr_Op_Type_Sub && y->type == Expr_Node_Constant)
+    {
+      op = Expr_Op_Type_Add;
+      y->value.i_value = -y->value.i_value;
+    }
+  if (y->type == Expr_Node_Constant && x->type == Expr_Node_Binop
+      && x->Right_Child->type == Expr_Node_Constant)
     {
-    /* Create a new expression structure.  */
-    Expr_Node_Value val;
-    val.op_value = op;
-    return Expr_Node_Create (Expr_Node_Binop, val, x, y);
-  }
+      if (op == x->value.op_value && x->value.op_value == Expr_Op_Type_Add)
+       {
+         x->Right_Child->value.i_value += y->value.i_value;
+         return x;
+       }
+    }
+
+  /* Create a new expression structure.  */
+  val.op_value = op;
+  return Expr_Node_Create (Expr_Node_Binop, val, x, y);
 }
 
 static Expr_Node *
This page took 0.027092 seconds and 4 git commands to generate.