gas/
[deliverable/binutils-gdb.git] / gas / config / bfin-parse.y
index b320c72d0cbd497a7005ac25e49387f15190aff2..4eaf6f1b7aa14a9d7cf5fe82e86a2c18e0a4b202 100644 (file)
@@ -1,5 +1,5 @@
 /* bfin-parse.y  ADI Blackfin parser
 /* bfin-parse.y  ADI Blackfin parser
-   Copyright 2005, 2006, 2007
+   Copyright 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -23,7 +23,7 @@
 #include "as.h"
 #include <obstack.h>
 
 #include "as.h"
 #include <obstack.h>
 
-#include "bfin-aux.h"  // opcode generating auxiliaries
+#include "bfin-aux.h"  /* Opcode generating auxiliaries.  */
 #include "libbfd.h"
 #include "elf/common.h"
 #include "elf/bfin.h"
 #include "libbfd.h"
 #include "elf/common.h"
 #include "elf/bfin.h"
        (value_match (expr, 24, 0, 2, 1))
 
 
        (value_match (expr, 24, 0, 2, 1))
 
 
-static int value_match (Expr_Node *expr, int sz, int sign, int mul, int issigned);
+static int value_match (Expr_Node *, int, int, int, int);
 
 extern FILE *errorf;
 extern INSTR_T insn;
 
 extern FILE *errorf;
 extern INSTR_T insn;
@@ -160,22 +160,25 @@ extern INSTR_T insn;
 static Expr_Node *binary (Expr_Op_Type, Expr_Node *, Expr_Node *);
 static Expr_Node *unary  (Expr_Op_Type, Expr_Node *);
 
 static Expr_Node *binary (Expr_Op_Type, Expr_Node *, Expr_Node *);
 static Expr_Node *unary  (Expr_Op_Type, Expr_Node *);
 
-static void notethat (char *format, ...);
+static void notethat (char *, ...);
 
 char *current_inputline;
 extern char *yytext;
 
 char *current_inputline;
 extern char *yytext;
-int yyerror (char *msg);
+int yyerror (char *);
+
+/* Used to set SRCx fields to all 1s as described in the PRM.  */
+static Register reg7 = {REG_R7, 0};
 
 void error (char *format, ...)
 {
     va_list ap;
 
 void error (char *format, ...)
 {
     va_list ap;
-    char buffer[2000];
-    
+    static char buffer[2000];
+
     va_start (ap, format);
     vsprintf (buffer, format, ap);
     va_end (ap);
 
     va_start (ap, format);
     vsprintf (buffer, format, ap);
     va_end (ap);
 
-    as_bad (buffer);
+    as_bad ("%s", buffer);
 }
 
 int
 }
 
 int
@@ -193,10 +196,10 @@ yyerror (char *msg)
 }
 
 static int
 }
 
 static int
-in_range_p (Expr_Node *expr, int from, int to, unsigned int mask)
+in_range_p (Expr_Node *exp, int from, int to, unsigned int mask)
 {
 {
-  int val = EXPR_VALUE (expr);
-  if (expr->type != Expr_Node_Constant)
+  int val = EXPR_VALUE (exp);
+  if (exp->type != Expr_Node_Constant)
     return 0;
   if (val < from || val > to)
     return 0;
     return 0;
   if (val < from || val > to)
     return 0;
@@ -212,6 +215,7 @@ extern int yylex (void);
 #define uimm5(x) EXPR_VALUE (x)
 #define imm6(x) EXPR_VALUE (x)
 #define imm7(x) EXPR_VALUE (x)
 #define uimm5(x) EXPR_VALUE (x)
 #define imm6(x) EXPR_VALUE (x)
 #define imm7(x) EXPR_VALUE (x)
+#define uimm8(x) EXPR_VALUE (x)
 #define imm16(x) EXPR_VALUE (x)
 #define uimm16s4(x) ((EXPR_VALUE (x)) >> 2)
 #define uimm16(x) EXPR_VALUE (x)
 #define imm16(x) EXPR_VALUE (x)
 #define uimm16s4(x) ((EXPR_VALUE (x)) >> 2)
 #define uimm16(x) EXPR_VALUE (x)
@@ -222,12 +226,6 @@ extern int yylex (void);
 
 /* Auxiliary functions.  */
 
 
 /* Auxiliary functions.  */
 
-static void
-neg_value (Expr_Node *expr)
-{
-  expr->value.i_value = -expr->value.i_value;
-}
-
 static int
 valid_dreg_pair (Register *reg1, Expr_Node *reg2)
 {
 static int
 valid_dreg_pair (Register *reg1, Expr_Node *reg2)
 {
@@ -264,6 +262,29 @@ 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->w == 1 && a->P == 1
+       && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_IU
+       && 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)
+      || (a->w == 0 && a->P == 0
+         && opt->mod != M_FU && opt->mod != M_IS && opt->mod != M_W32))
+    return -1;
+
+  return 0;
+}
+
 /* Check (vector) mac funcs and ops.  */
 
 static int
 /* Check (vector) mac funcs and ops.  */
 
 static int
@@ -274,8 +295,13 @@ check_macfuncs (Macfunc *aa, Opt_mode *opa,
   Macfunc mtmp;
   Opt_mode otmp;
 
   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 a0macfunc comes before a1macfunc, swap them.  */
-       
+
   if (aa->n == 0)
     {
       /*  (M) is not allowed here.  */
   if (aa->n == 0)
     {
       /*  (M) is not allowed here.  */
@@ -291,16 +317,14 @@ check_macfuncs (Macfunc *aa, Opt_mode *opa,
     {
       if (opb->MM != 0)
        return yyerror ("(M) not allowed with A0MAC");
     {
       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 (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;
     {
       if (check_multiply_halfregs (aa, ab) < 0)
        return -1;
@@ -315,27 +339,29 @@ check_macfuncs (Macfunc *aa, Opt_mode *opa,
       aa->s1.regno |= (ab->s1.regno & CODE_MASK);
     }
 
       aa->s1.regno |= (ab->s1.regno & CODE_MASK);
     }
 
-  if (aa->w == ab->w  && aa->P != ab->P)
+  if (aa->w == ab->w && aa->P != ab->P)
+    return yyerror ("Destination Dreg sizes (full or half) must match");
+
+  if (aa->w && ab->w)
     {
     {
-      return yyerror ("macfuncs must differ");
-      if (aa->w && (aa->dst.regno - ab->dst.regno != 1))
-       return yyerror ("Destination Dregs must differ by one");
+      if (aa->P && (aa->dst.regno - ab->dst.regno) != 1)
+       return yyerror ("Destination Dregs (full) must differ by one");
+      if (!aa->P && aa->dst.regno != ab->dst.regno)
+       return yyerror ("Destination Dregs (half) must match");
     }
     }
-  /* We assign to full regs, thus obey even/odd rules.  */
-  else if ((aa->w && aa->P && IS_EVEN (aa->dst)) 
-          || (ab->w && ab->P && !IS_EVEN (ab->dst)))
-    return yyerror ("Even/Odd register assignment mismatch");
-  /* We assign to half regs, thus obey hi/low rules.  */
-  else if ( (aa->w && !aa->P && !IS_H (aa->dst)) 
-           || (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 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;    
+  return 0;
 }
 
 
 }
 
 
@@ -361,6 +387,62 @@ is_group2 (INSTR_T x)
   return 0;
 }
 
   return 0;
 }
 
+static int
+is_store (INSTR_T x)
+{
+  if (!x)
+    return 0;
+
+  if ((x->value & 0xf000) == 0x8000)
+    {
+      int aop = ((x->value >> 9) & 0x3);
+      int w = ((x->value >> 11) & 0x1);
+      if (!w || aop == 3)
+       return 0;
+      return 1;
+    }
+
+  if (((x->value & 0xFF60) == 0x9E60) ||  /* dagMODim_0 */
+      ((x->value & 0xFFF0) == 0x9F60))    /* dagMODik_0 */
+    return 0;
+
+  /* decode_dspLDST_0 */
+  if ((x->value & 0xFC00) == 0x9C00)
+    {
+      int w = ((x->value >> 9) & 0x1);
+      if (w)
+       return 1;
+    }
+
+  return 0;
+}
+
+static INSTR_T
+gen_multi_instr_1 (INSTR_T dsp32, INSTR_T dsp16_grp1, INSTR_T dsp16_grp2)
+{
+  int mask1 = dsp32 ? insn_regmask (dsp32->value, dsp32->next->value) : 0;
+  int mask2 = dsp16_grp1 ? insn_regmask (dsp16_grp1->value, 0) : 0;
+  int mask3 = dsp16_grp2 ? insn_regmask (dsp16_grp2->value, 0) : 0;
+
+  if ((mask1 & mask2) || (mask1 & mask3) || (mask2 & mask3))
+    yyerror ("resource conflict in multi-issue instruction");
+
+  /* Anomaly 05000074 */
+  if (ENABLE_AC_05000074
+      && dsp32 != NULL && dsp16_grp1 != NULL
+      && (dsp32->value & 0xf780) == 0xc680
+      && ((dsp16_grp1->value & 0xfe40) == 0x9240
+         || (dsp16_grp1->value & 0xfe08) == 0xba08
+         || (dsp16_grp1->value & 0xfc00) == 0xbc00))
+    yyerror ("anomaly 05000074 - Multi-Issue Instruction with \
+dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported");
+
+  if (is_store (dsp16_grp1) && is_store (dsp16_grp2))
+    yyerror ("Only one instruction in multi-issue instruction can be a store");
+
+  return bfin_gen_multi_instr (dsp32, dsp16_grp1, dsp16_grp2);
+}
+
 %}
 
 %union {
 %}
 
 %union {
@@ -380,7 +462,7 @@ is_group2 (INSTR_T x)
 
 /* Vector Specific.  */
 %token BYTEOP16P BYTEOP16M
 
 /* Vector Specific.  */
 %token BYTEOP16P BYTEOP16M
-%token BYTEOP1P BYTEOP2P BYTEOP2M BYTEOP3P
+%token BYTEOP1P BYTEOP2P BYTEOP3P
 %token BYTEUNPACK BYTEPACK
 %token PACK
 %token SAA
 %token BYTEUNPACK BYTEPACK
 %token PACK
 %token SAA
@@ -437,7 +519,7 @@ is_group2 (INSTR_T x)
 %token SHIFT LSHIFT ASHIFT BXORSHIFT
 %token _GREATER_GREATER_GREATER_THAN_ASSIGN
 %token ROT
 %token SHIFT LSHIFT ASHIFT BXORSHIFT
 %token _GREATER_GREATER_GREATER_THAN_ASSIGN
 %token ROT
-%token LESS_LESS GREATER_GREATER  
+%token LESS_LESS GREATER_GREATER
 %token _GREATER_GREATER_GREATER
 %token _LESS_LESS_ASSIGN _GREATER_GREATER_ASSIGN
 %token DIVS DIVQ
 %token _GREATER_GREATER_GREATER
 %token _LESS_LESS_ASSIGN _GREATER_GREATER_ASSIGN
 %token DIVS DIVQ
@@ -504,8 +586,8 @@ is_group2 (INSTR_T x)
 %type <reg> a_plusassign
 %type <reg> a_minusassign
 %type <macfunc> multiply_halfregs
 %type <reg> a_plusassign
 %type <reg> a_minusassign
 %type <macfunc> multiply_halfregs
-%type <macfunc> assign_macfunc 
-%type <macfunc> a_macfunc 
+%type <macfunc> assign_macfunc
+%type <macfunc> a_macfunc
 %type <expr> expr_1
 %type <instr> asm_1
 %type <r0> vmod
 %type <expr> expr_1
 %type <instr> asm_1
 %type <r0> vmod
@@ -525,11 +607,11 @@ is_group2 (INSTR_T x)
 %type <reg> REG_A_DOUBLE_ZERO
 %type <reg> REG_A_DOUBLE_ONE
 %type <reg> REG_A
 %type <reg> REG_A_DOUBLE_ZERO
 %type <reg> REG_A_DOUBLE_ONE
 %type <reg> REG_A
-%type <reg> STATUS_REG 
+%type <reg> STATUS_REG
 %type <expr> expr
 %type <r0> xpmod
 %type <r0> xpmod1
 %type <expr> expr
 %type <r0> xpmod
 %type <r0> xpmod1
-%type <modcodes> smod 
+%type <modcodes> smod
 %type <modcodes> b3_op
 %type <modcodes> rnd_op
 %type <modcodes> post_op
 %type <modcodes> b3_op
 %type <modcodes> rnd_op
 %type <modcodes> post_op
@@ -564,7 +646,7 @@ is_group2 (INSTR_T x)
 %right TILDA BANG
 %start statement
 %%
 %right TILDA BANG
 %start statement
 %%
-statement: 
+statement:
        | asm
        {
          insn = $1;
        | asm
        {
          insn = $1;
@@ -584,27 +666,27 @@ asm: asm_1 SEMICOLON
          if (($1->value & 0xf800) == 0xc000)
            {
              if (is_group1 ($3) && is_group2 ($5))
          if (($1->value & 0xf800) == 0xc000)
            {
              if (is_group1 ($3) && is_group2 ($5))
-               $$ = bfin_gen_multi_instr ($1, $3, $5);
+               $$ = gen_multi_instr_1 ($1, $3, $5);
              else if (is_group2 ($3) && is_group1 ($5))
              else if (is_group2 ($3) && is_group1 ($5))
-               $$ = bfin_gen_multi_instr ($1, $5, $3);
+               $$ = gen_multi_instr_1 ($1, $5, $3);
              else
                return yyerror ("Wrong 16 bit instructions groups, slot 2 and slot 3 must be 16-bit instrution group");
            }
          else if (($3->value & 0xf800) == 0xc000)
            {
              if (is_group1 ($1) && is_group2 ($5))
              else
                return yyerror ("Wrong 16 bit instructions groups, slot 2 and slot 3 must be 16-bit instrution group");
            }
          else if (($3->value & 0xf800) == 0xc000)
            {
              if (is_group1 ($1) && is_group2 ($5))
-               $$ = bfin_gen_multi_instr ($3, $1, $5);
+               $$ = gen_multi_instr_1 ($3, $1, $5);
              else if (is_group2 ($1) && is_group1 ($5))
              else if (is_group2 ($1) && is_group1 ($5))
-               $$ = bfin_gen_multi_instr ($3, $5, $1);
+               $$ = gen_multi_instr_1 ($3, $5, $1);
              else
                return yyerror ("Wrong 16 bit instructions groups, slot 1 and slot 3 must be 16-bit instrution group");
            }
          else if (($5->value & 0xf800) == 0xc000)
            {
              if (is_group1 ($1) && is_group2 ($3))
              else
                return yyerror ("Wrong 16 bit instructions groups, slot 1 and slot 3 must be 16-bit instrution group");
            }
          else if (($5->value & 0xf800) == 0xc000)
            {
              if (is_group1 ($1) && is_group2 ($3))
-               $$ = bfin_gen_multi_instr ($5, $1, $3);
+               $$ = gen_multi_instr_1 ($5, $1, $3);
              else if (is_group2 ($1) && is_group1 ($3))
              else if (is_group2 ($1) && is_group1 ($3))
-               $$ = bfin_gen_multi_instr ($5, $3, $1);
+               $$ = gen_multi_instr_1 ($5, $3, $1);
              else
                return yyerror ("Wrong 16 bit instructions groups, slot 1 and slot 2 must be 16-bit instrution group");
            }
              else
                return yyerror ("Wrong 16 bit instructions groups, slot 1 and slot 2 must be 16-bit instrution group");
            }
@@ -617,25 +699,25 @@ asm: asm_1 SEMICOLON
          if (($1->value & 0xf800) == 0xc000)
            {
              if (is_group1 ($3))
          if (($1->value & 0xf800) == 0xc000)
            {
              if (is_group1 ($3))
-               $$ = bfin_gen_multi_instr ($1, $3, 0);
+               $$ = gen_multi_instr_1 ($1, $3, 0);
              else if (is_group2 ($3))
              else if (is_group2 ($3))
-               $$ = bfin_gen_multi_instr ($1, 0, $3);
+               $$ = gen_multi_instr_1 ($1, 0, $3);
              else
                return yyerror ("Wrong 16 bit instructions groups, slot 2 must be the 16-bit instruction group");
            }
          else if (($3->value & 0xf800) == 0xc000)
            {
              if (is_group1 ($1))
              else
                return yyerror ("Wrong 16 bit instructions groups, slot 2 must be the 16-bit instruction group");
            }
          else if (($3->value & 0xf800) == 0xc000)
            {
              if (is_group1 ($1))
-               $$ = bfin_gen_multi_instr ($3, $1, 0);
+               $$ = gen_multi_instr_1 ($3, $1, 0);
              else if (is_group2 ($1))
              else if (is_group2 ($1))
-               $$ = bfin_gen_multi_instr ($3, 0, $1);
+               $$ = gen_multi_instr_1 ($3, 0, $1);
              else
                return yyerror ("Wrong 16 bit instructions groups, slot 1 must be the 16-bit instruction group");
            }
          else if (is_group1 ($1) && is_group2 ($3))
              else
                return yyerror ("Wrong 16 bit instructions groups, slot 1 must be the 16-bit instruction group");
            }
          else if (is_group1 ($1) && is_group2 ($3))
-             $$ = bfin_gen_multi_instr (0, $1, $3);
+             $$ = gen_multi_instr_1 (0, $1, $3);
          else if (is_group2 ($1) && is_group1 ($3))
          else if (is_group2 ($1) && is_group1 ($3))
-           $$ = bfin_gen_multi_instr (0, $3, $1);
+           $$ = gen_multi_instr_1 (0, $3, $1);
          else
            return yyerror ("Wrong 16 bit instructions groups, slot 1 and slot 2 must be the 16-bit instruction group");
        }
          else
            return yyerror ("Wrong 16 bit instructions groups, slot 1 and slot 2 must be the 16-bit instruction group");
        }
@@ -649,7 +731,7 @@ asm: asm_1 SEMICOLON
 
 /* DSPMAC.  */
 
 
 /* DSPMAC.  */
 
-asm_1:   
+asm_1:
        MNOP
        {
          $$ = DSP32MAC (3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
        MNOP
        {
          $$ = DSP32MAC (3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
@@ -660,9 +742,12 @@ asm_1:
          int w0 = 0, w1 = 0;
          int h00, h10, h01, h11;
 
          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 ($1.n == 0)
            {
-             if ($2.MM) 
+             if ($2.MM)
                return yyerror ("(m) not allowed with a0 unit");
              op1 = 3;
              op0 = $1.op;
                return yyerror ("(m) not allowed with a0 unit");
              op1 = 3;
              op0 = $1.op;
@@ -693,7 +778,7 @@ asm_1:
        {
          Register *dst;
 
        {
          Register *dst;
 
-         if (check_macfuncs (&$1, &$2, &$4, &$5) < 0) 
+         if (check_macfuncs (&$1, &$2, &$4, &$5) < 0)
            return -1;
          notethat ("assign_macfunc (.), assign_macfunc (.)\n");
 
            return -1;
          notethat ("assign_macfunc (.), assign_macfunc (.)\n");
 
@@ -719,17 +804,17 @@ asm_1:
          if (IS_DREG ($1) && !IS_A1 ($4) && IS_A1 ($5))
            {
              notethat ("dsp32alu: dregs = ( A0 += A1 )\n");
          if (IS_DREG ($1) && !IS_A1 ($4) && IS_A1 ($5))
            {
              notethat ("dsp32alu: dregs = ( A0 += A1 )\n");
-             $$ = DSP32ALU (11, 0, 0, &$1, 0, 0, 0, 0, 0);
+             $$ = DSP32ALU (11, 0, 0, &$1, &reg7, &reg7, 0, 0, 0);
            }
            }
-         else 
+         else
            return yyerror ("Register mismatch");
            return yyerror ("Register mismatch");
-       }       
+       }
        | HALF_REG ASSIGN LPAREN a_plusassign REG_A RPAREN
        {
          if (!IS_A1 ($4) && IS_A1 ($5))
            {
              notethat ("dsp32alu: dregs_half = ( A0 += A1 )\n");
        | HALF_REG ASSIGN LPAREN a_plusassign REG_A RPAREN
        {
          if (!IS_A1 ($4) && IS_A1 ($5))
            {
              notethat ("dsp32alu: dregs_half = ( A0 += A1 )\n");
-             $$ = DSP32ALU (11, IS_H ($1), 0, &$1, 0, 0, 0, 0, 1);
+             $$ = DSP32ALU (11, IS_H ($1), 0, &$1, &reg7, &reg7, 0, 0, 1);
            }
          else
            return yyerror ("Register mismatch");
            }
          else
            return yyerror ("Register mismatch");
@@ -749,22 +834,26 @@ asm_1:
        {
          if (!IS_DREG ($2) || !IS_DREG ($4))
            return yyerror ("Dregs expected");
        {
          if (!IS_DREG ($2) || !IS_DREG ($4))
            return yyerror ("Dregs expected");
+         else if (REG_SAME ($2, $4))
+           return yyerror ("Illegal dest register combination");
          else if (!valid_dreg_pair (&$9, $11))
            return yyerror ("Bad dreg pair");
          else if (!valid_dreg_pair (&$13, $15))
            return yyerror ("Bad dreg pair");
          else
            {
          else if (!valid_dreg_pair (&$9, $11))
            return yyerror ("Bad dreg pair");
          else if (!valid_dreg_pair (&$13, $15))
            return yyerror ("Bad dreg pair");
          else
            {
-             notethat ("dsp32alu: (dregs , dregs ) = BYTEOP16P (dregs_pair , dregs_pair ) (half)\n");
+             notethat ("dsp32alu: (dregs , dregs ) = BYTEOP16P (dregs_pair , dregs_pair ) (aligndir)\n");
              $$ = DSP32ALU (21, 0, &$2, &$4, &$9, &$13, $17.r0, 0, 0);
            }
        }
 
        | LPAREN REG COMMA REG RPAREN ASSIGN BYTEOP16M LPAREN REG COLON expr COMMA
              $$ = DSP32ALU (21, 0, &$2, &$4, &$9, &$13, $17.r0, 0, 0);
            }
        }
 
        | LPAREN REG COMMA REG RPAREN ASSIGN BYTEOP16M LPAREN REG COLON expr COMMA
-         REG COLON expr RPAREN aligndir 
+         REG COLON expr RPAREN aligndir
        {
        {
-         if (!IS_DREG ($2) || !IS_DREG($4))
+         if (!IS_DREG ($2) || !IS_DREG ($4))
            return yyerror ("Dregs expected");
            return yyerror ("Dregs expected");
+         else if (REG_SAME ($2, $4))
+           return yyerror ("Illegal dest register combination");
          else if (!valid_dreg_pair (&$9, $11))
            return yyerror ("Bad dreg pair");
          else if (!valid_dreg_pair (&$13, $15))
          else if (!valid_dreg_pair (&$9, $11))
            return yyerror ("Bad dreg pair");
          else if (!valid_dreg_pair (&$13, $15))
@@ -780,6 +869,8 @@ asm_1:
        {
          if (!IS_DREG ($2) || !IS_DREG ($4))
            return yyerror ("Dregs expected");
        {
          if (!IS_DREG ($2) || !IS_DREG ($4))
            return yyerror ("Dregs expected");
+         else if (REG_SAME ($2, $4))
+           return yyerror ("Illegal dest register combination");
          else if (!valid_dreg_pair (&$8, $10))
            return yyerror ("Bad dreg pair");
          else
          else if (!valid_dreg_pair (&$8, $10))
            return yyerror ("Bad dreg pair");
          else
@@ -790,6 +881,9 @@ asm_1:
        }
        | LPAREN REG COMMA REG RPAREN ASSIGN SEARCH REG LPAREN searchmod RPAREN
        {
        }
        | LPAREN REG COMMA REG RPAREN ASSIGN SEARCH REG LPAREN searchmod RPAREN
        {
+         if (REG_SAME ($2, $4))
+           return yyerror ("Illegal dest register combination");
+
          if (IS_DREG ($2) && IS_DREG ($4) && IS_DREG ($8))
            {
              notethat ("dsp32alu: (dregs , dregs ) = SEARCH dregs (searchmod)\n");
          if (IS_DREG ($2) && IS_DREG ($4) && IS_DREG ($8))
            {
              notethat ("dsp32alu: (dregs , dregs ) = SEARCH dregs (searchmod)\n");
@@ -801,30 +895,36 @@ asm_1:
        | REG ASSIGN A_ONE_DOT_L PLUS A_ONE_DOT_H COMMA
          REG ASSIGN A_ZERO_DOT_L PLUS A_ZERO_DOT_H
        {
        | REG ASSIGN A_ONE_DOT_L PLUS A_ONE_DOT_H COMMA
          REG ASSIGN A_ZERO_DOT_L PLUS A_ZERO_DOT_H
        {
+         if (REG_SAME ($1, $7))
+           return yyerror ("Illegal dest register combination");
+
          if (IS_DREG ($1) && IS_DREG ($7))
            {
              notethat ("dsp32alu: dregs = A1.l + A1.h, dregs = A0.l + A0.h  \n");
          if (IS_DREG ($1) && IS_DREG ($7))
            {
              notethat ("dsp32alu: dregs = A1.l + A1.h, dregs = A0.l + A0.h  \n");
-             $$ = DSP32ALU (12, 0, &$1, &$7, 0, 0, 0, 0, 1);
+             $$ = DSP32ALU (12, 0, &$1, &$7, &reg7, &reg7, 0, 0, 1);
            }
          else
            return yyerror ("Register mismatch");
        }
 
 
            }
          else
            return yyerror ("Register mismatch");
        }
 
 
-       | REG ASSIGN REG_A PLUS REG_A COMMA REG ASSIGN REG_A MINUS REG_A amod1 
+       | REG ASSIGN REG_A PLUS REG_A COMMA REG ASSIGN REG_A MINUS REG_A amod1
        {
        {
+         if (REG_SAME ($1, $7))
+           return yyerror ("Resource conflict in dest reg");
+
          if (IS_DREG ($1) && IS_DREG ($7) && !REG_SAME ($3, $5)
              && IS_A1 ($9) && !IS_A1 ($11))
            {
              notethat ("dsp32alu: dregs = A1 + A0 , dregs = A1 - A0 (amod1)\n");
          if (IS_DREG ($1) && IS_DREG ($7) && !REG_SAME ($3, $5)
              && IS_A1 ($9) && !IS_A1 ($11))
            {
              notethat ("dsp32alu: dregs = A1 + A0 , dregs = A1 - A0 (amod1)\n");
-             $$ = DSP32ALU (17, 0, &$1, &$7, 0, 0, $12.s0, $12.x0, 0);
-             
+             $$ = DSP32ALU (17, 0, &$1, &$7, &reg7, &reg7, $12.s0, $12.x0, 0);
+
            }
          else if (IS_DREG ($1) && IS_DREG ($7) && !REG_SAME ($3, $5)
                   && !IS_A1 ($9) && IS_A1 ($11))
            {
              notethat ("dsp32alu: dregs = A0 + A1 , dregs = A0 - A1 (amod1)\n");
            }
          else if (IS_DREG ($1) && IS_DREG ($7) && !REG_SAME ($3, $5)
                   && !IS_A1 ($9) && IS_A1 ($11))
            {
              notethat ("dsp32alu: dregs = A0 + A1 , dregs = A0 - A1 (amod1)\n");
-             $$ = DSP32ALU (17, 0, &$1, &$7, 0, 0, $12.s0, $12.x0, 1);
+             $$ = DSP32ALU (17, 0, &$1, &$7, &reg7, &reg7, $12.s0, $12.x0, 1);
            }
          else
            return yyerror ("Register mismatch");
            }
          else
            return yyerror ("Register mismatch");
@@ -832,7 +932,7 @@ asm_1:
 
        | REG ASSIGN REG plus_minus REG COMMA REG ASSIGN REG plus_minus REG amod1
        {
 
        | REG ASSIGN REG plus_minus REG COMMA REG ASSIGN REG plus_minus REG amod1
        {
-         if ($4.r0 == $10.r0) 
+         if ($4.r0 == $10.r0)
            return yyerror ("Operators must differ");
 
          if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5)
            return yyerror ("Operators must differ");
 
          if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5)
@@ -848,15 +948,17 @@ asm_1:
 
 /*  Bar Operations.  */
 
 
 /*  Bar Operations.  */
 
-       | REG ASSIGN REG op_bar_op REG COMMA REG ASSIGN REG op_bar_op REG amod2 
+       | REG ASSIGN REG op_bar_op REG COMMA REG ASSIGN REG op_bar_op REG amod2
        {
          if (!REG_SAME ($3, $9) || !REG_SAME ($5, $11))
            return yyerror ("Differing source registers");
 
        {
          if (!REG_SAME ($3, $9) || !REG_SAME ($5, $11))
            return yyerror ("Differing source registers");
 
-         if (!IS_DREG ($1) || !IS_DREG ($3) || !IS_DREG ($5) || !IS_DREG ($7)) 
+         if (!IS_DREG ($1) || !IS_DREG ($3) || !IS_DREG ($5) || !IS_DREG ($7))
            return yyerror ("Dregs expected");
 
            return yyerror ("Dregs expected");
 
-       
+         if (REG_SAME ($1, $7))
+           return yyerror ("Resource conflict in dest reg");
+
          if ($4.r0 == 1 && $10.r0 == 2)
            {
              notethat ("dsp32alu:  dregs = dregs .|. dregs , dregs = dregs .|. dregs (amod2)\n");
          if ($4.r0 == 1 && $10.r0 == 2)
            {
              notethat ("dsp32alu:  dregs = dregs .|. dregs , dregs = dregs .|. dregs (amod2)\n");
@@ -896,7 +998,7 @@ asm_1:
        | a_assign ABS REG_A
        {
          notethat ("dsp32alu: Ax = ABS Ax\n");
        | a_assign ABS REG_A
        {
          notethat ("dsp32alu: Ax = ABS Ax\n");
-         $$ = DSP32ALU (16, IS_A1 ($1), 0, 0, 0, 0, 0, 0, IS_A1 ($3));
+         $$ = DSP32ALU (16, IS_A1 ($1), 0, 0, &reg7, &reg7, 0, 0, IS_A1 ($3));
        }
        | A_ZERO_DOT_L ASSIGN HALF_REG
        {
        }
        | A_ZERO_DOT_L ASSIGN HALF_REG
        {
@@ -975,22 +1077,6 @@ asm_1:
            }
        }
 
            }
        }
 
-       | REG ASSIGN BYTEOP2M LPAREN REG COLON expr COMMA REG COLON expr RPAREN
-         rnd_op
-       {
-         if (!IS_DREG ($1))
-           return yyerror ("Dregs expected");
-         else if (!valid_dreg_pair (&$5, $7))
-           return yyerror ("Bad dreg pair");
-         else if (!valid_dreg_pair (&$9, $11))
-           return yyerror ("Bad dreg pair");
-         else
-           {
-             notethat ("dsp32alu: dregs = BYTEOP2P (dregs_pair , dregs_pair ) (rnd_op)\n");
-             $$ = DSP32ALU (22, $13.r0, 0, &$1, &$5, &$9, $13.s0, 0, $13.x0);
-           }
-       }
-
        | REG ASSIGN BYTEOP3P LPAREN REG COLON expr COMMA REG COLON expr RPAREN
          b3_op
        {
        | REG ASSIGN BYTEOP3P LPAREN REG COLON expr COMMA REG COLON expr RPAREN
          b3_op
        {
@@ -1019,7 +1105,7 @@ asm_1:
        }
 
        | HALF_REG ASSIGN HALF_REG ASSIGN SIGN LPAREN HALF_REG RPAREN STAR
        }
 
        | HALF_REG ASSIGN HALF_REG ASSIGN SIGN LPAREN HALF_REG RPAREN STAR
-         HALF_REG PLUS SIGN LPAREN HALF_REG RPAREN STAR HALF_REG 
+         HALF_REG PLUS SIGN LPAREN HALF_REG RPAREN STAR HALF_REG
        {
          if (IS_HCOMPL ($1, $3) && IS_HCOMPL ($7, $14) && IS_HCOMPL ($10, $17))
            {
        {
          if (IS_HCOMPL ($1, $3) && IS_HCOMPL ($7, $14) && IS_HCOMPL ($10, $17))
            {
@@ -1032,7 +1118,7 @@ asm_1:
          else
            return yyerror ("Dregs expected");
        }
          else
            return yyerror ("Dregs expected");
        }
-       | REG ASSIGN REG plus_minus REG amod1 
+       | REG ASSIGN REG plus_minus REG amod1
        {
          if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
            {
        {
          if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
            {
@@ -1079,7 +1165,7 @@ asm_1:
        | a_assign MINUS REG_A
        {
          notethat ("dsp32alu: Ax = - Ax\n");
        | a_assign MINUS REG_A
        {
          notethat ("dsp32alu: Ax = - Ax\n");
-         $$ = DSP32ALU (14, IS_A1 ($1), 0, 0, 0, 0, 0, 0, IS_A1 ($3));
+         $$ = DSP32ALU (14, IS_A1 ($1), 0, 0, &reg7, &reg7, 0, 0, IS_A1 ($3));
        }
        | HALF_REG ASSIGN HALF_REG plus_minus HALF_REG amod1
        {
        }
        | HALF_REG ASSIGN HALF_REG plus_minus HALF_REG amod1
        {
@@ -1092,7 +1178,7 @@ asm_1:
          if (EXPR_VALUE ($3) == 0 && !REG_SAME ($1, $2))
            {
              notethat ("dsp32alu: A1 = A0 = 0\n");
          if (EXPR_VALUE ($3) == 0 && !REG_SAME ($1, $2))
            {
              notethat ("dsp32alu: A1 = A0 = 0\n");
-             $$ = DSP32ALU (8, 0, 0, 0, 0, 0, 0, 0, 2);
+             $$ = DSP32ALU (8, 0, 0, 0, &reg7, &reg7, 0, 0, 2);
            }
          else
            return yyerror ("Bad value, 0 expected");
            }
          else
            return yyerror ("Bad value, 0 expected");
@@ -1104,7 +1190,7 @@ asm_1:
          if (REG_SAME ($1, $2))
            {
              notethat ("dsp32alu: Ax = Ax (S)\n");
          if (REG_SAME ($1, $2))
            {
              notethat ("dsp32alu: Ax = Ax (S)\n");
-             $$ = DSP32ALU (8, 0, 0, 0, 0, 0, 1, 0, IS_A1 ($1));
+             $$ = DSP32ALU (8, 0, 0, 0, &reg7, &reg7, 1, 0, IS_A1 ($1));
            }
          else
            return yyerror ("Registers must be equal");
            }
          else
            return yyerror ("Registers must be equal");
@@ -1143,12 +1229,12 @@ asm_1:
            return yyerror ("Dregs expected");
        }
 
            return yyerror ("Dregs expected");
        }
 
-       | a_assign REG_A 
+       | a_assign REG_A
        {
          if (!REG_SAME ($1, $2))
            {
              notethat ("dsp32alu: An = Am\n");
        {
          if (!REG_SAME ($1, $2))
            {
              notethat ("dsp32alu: An = Am\n");
-             $$ = DSP32ALU (8, 0, 0, 0, 0, 0, IS_A1 ($1), 0, 3);
+             $$ = DSP32ALU (8, 0, 0, 0, &reg7, &reg7, IS_A1 ($1), 0, 3);
            }
          else
            return yyerror ("Accu reg arguments must differ");
            }
          else
            return yyerror ("Accu reg arguments must differ");
@@ -1244,7 +1330,7 @@ asm_1:
                  notethat ("LDIMMhalf: regs = luimm16 (x)\n");
                  /* reg, H, S, Z.   */
                  $$ = LDIMMHALF_R5 (&$1, 0, 1, 0, $3);
                  notethat ("LDIMMhalf: regs = luimm16 (x)\n");
                  /* reg, H, S, Z.   */
                  $$ = LDIMMHALF_R5 (&$1, 0, 1, 0, $3);
-               } 
+               }
            }
          else
            {
            }
          else
            {
@@ -1268,18 +1354,18 @@ asm_1:
          if (IS_DREG ($1) && $3.regno == REG_A0x)
            {
              notethat ("dsp32alu: dregs_lo = A0.x\n");
          if (IS_DREG ($1) && $3.regno == REG_A0x)
            {
              notethat ("dsp32alu: dregs_lo = A0.x\n");
-             $$ = DSP32ALU (10, 0, 0, &$1, 0, 0, 0, 0, 0);
+             $$ = DSP32ALU (10, 0, 0, &$1, &reg7, &reg7, 0, 0, 0);
            }
          else if (IS_DREG ($1) && $3.regno == REG_A1x)
            {
              notethat ("dsp32alu: dregs_lo = A1.x\n");
            }
          else if (IS_DREG ($1) && $3.regno == REG_A1x)
            {
              notethat ("dsp32alu: dregs_lo = A1.x\n");
-             $$ = DSP32ALU (10, 0, 0, &$1, 0, 0, 0, 0, 1);
+             $$ = DSP32ALU (10, 0, 0, &$1, &reg7, &reg7, 0, 0, 1);
            }
          else
            return yyerror ("Register mismatch");
        }
 
            }
          else
            return yyerror ("Register mismatch");
        }
 
-       | REG ASSIGN REG op_bar_op REG amod0 
+       | REG ASSIGN REG op_bar_op REG amod0
        {
          if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
            {
        {
          if (IS_DREG ($1) && IS_DREG ($3) && IS_DREG ($5))
            {
@@ -1306,7 +1392,7 @@ asm_1:
          if (REG_SAME ($1, $3) && REG_SAME ($5, $7) && !REG_SAME ($1, $5))
            {
              notethat ("dsp32alu: A1 = ABS A1 , A0 = ABS A0\n");
          if (REG_SAME ($1, $3) && REG_SAME ($5, $7) && !REG_SAME ($1, $5))
            {
              notethat ("dsp32alu: A1 = ABS A1 , A0 = ABS A0\n");
-             $$ = DSP32ALU (16, 0, 0, 0, 0, 0, 0, 0, 3);
+             $$ = DSP32ALU (16, 0, 0, 0, &reg7, &reg7, 0, 0, 3);
            }
          else
            return yyerror ("Register mismatch");
            }
          else
            return yyerror ("Register mismatch");
@@ -1317,7 +1403,7 @@ asm_1:
          if (REG_SAME ($1, $3) && REG_SAME ($5, $7) && !REG_SAME ($1, $5))
            {
              notethat ("dsp32alu: A1 = - A1 , A0 = - A0\n");
          if (REG_SAME ($1, $3) && REG_SAME ($5, $7) && !REG_SAME ($1, $5))
            {
              notethat ("dsp32alu: A1 = - A1 , A0 = - A0\n");
-             $$ = DSP32ALU (14, 0, 0, 0, 0, 0, 0, 0, 3);
+             $$ = DSP32ALU (14, 0, 0, 0, &reg7, &reg7, 0, 0, 3);
            }
          else
            return yyerror ("Register mismatch");
            }
          else
            return yyerror ("Register mismatch");
@@ -1328,7 +1414,7 @@ asm_1:
          if (!IS_A1 ($1) && IS_A1 ($2))
            {
              notethat ("dsp32alu: A0 -= A1\n");
          if (!IS_A1 ($1) && IS_A1 ($2))
            {
              notethat ("dsp32alu: A0 -= A1\n");
-             $$ = DSP32ALU (11, 0, 0, 0, 0, 0, $3.r0, 0, 3);
+             $$ = DSP32ALU (11, 0, 0, 0, &reg7, &reg7, $3.r0, 0, 3);
            }
          else
            return yyerror ("Register mismatch");
            }
          else
            return yyerror ("Register mismatch");
@@ -1388,7 +1474,7 @@ asm_1:
          if (!IS_A1 ($1) && IS_A1 ($3))
            {
              notethat ("dsp32alu: A0 += A1 (W32)\n");
          if (!IS_A1 ($1) && IS_A1 ($3))
            {
              notethat ("dsp32alu: A0 += A1 (W32)\n");
-             $$ = DSP32ALU (11, 0, 0, 0, 0, 0, $4.r0, 0, 2);
+             $$ = DSP32ALU (11, 0, 0, 0, &reg7, &reg7, $4.r0, 0, 2);
            }
          else
            return yyerror ("Register mismatch");
            }
          else
            return yyerror ("Register mismatch");
@@ -1467,7 +1553,7 @@ asm_1:
          if (REG_SAME ($1, $2) && REG_SAME ($7, $8) && !REG_SAME ($1, $7))
            {
              notethat ("dsp32alu: A1 = A1 (S) , A0 = A0 (S)\n");
          if (REG_SAME ($1, $2) && REG_SAME ($7, $8) && !REG_SAME ($1, $7))
            {
              notethat ("dsp32alu: A1 = A1 (S) , A0 = A0 (S)\n");
-             $$ = DSP32ALU (8, 0, 0, 0, 0, 0, 1, 0, 2);
+             $$ = DSP32ALU (8, 0, 0, 0, &reg7, &reg7, 1, 0, 2);
            }
          else
            return yyerror ("Register mismatch");
            }
          else
            return yyerror ("Register mismatch");
@@ -1510,7 +1596,7 @@ asm_1:
          else
            return yyerror ("Register mismatch");
        }
          else
            return yyerror ("Register mismatch");
        }
-                       
+
 /*  COMP3 CCFLAG.  */
        | REG ASSIGN REG BAR REG
        {
 /*  COMP3 CCFLAG.  */
        | REG ASSIGN REG BAR REG
        {
@@ -1574,16 +1660,20 @@ asm_1:
        }
        | CCREG ASSIGN REG LESS_THAN REG iu_or_nothing
        {
        }
        | CCREG ASSIGN REG LESS_THAN REG iu_or_nothing
        {
-         if (REG_CLASS($3) == REG_CLASS($5))
+         if ((IS_DREG ($3) && IS_DREG ($5))
+             || (IS_PREG ($3) && IS_PREG ($5)))
            {
              notethat ("CCflag: CC = dpregs < dpregs\n");
              $$ = CCFLAG (&$3, $5.regno & CODE_MASK, $6.r0, 0, IS_PREG ($3) ? 1 : 0);
            }
          else
            {
              notethat ("CCflag: CC = dpregs < dpregs\n");
              $$ = CCFLAG (&$3, $5.regno & CODE_MASK, $6.r0, 0, IS_PREG ($3) ? 1 : 0);
            }
          else
-           return yyerror ("Compare only of same register class");
+           return yyerror ("Bad register in comparison");
        }
        | CCREG ASSIGN REG LESS_THAN expr iu_or_nothing
        {
        }
        | CCREG ASSIGN REG LESS_THAN expr iu_or_nothing
        {
+         if (!IS_DREG ($3) && !IS_PREG ($3))
+           return yyerror ("Bad register in comparison");
+
          if (($6.r0 == 1 && IS_IMM ($5, 3))
              || ($6.r0 == 3 && IS_UIMM ($5, 3)))
            {
          if (($6.r0 == 1 && IS_IMM ($5, 3))
              || ($6.r0 == 3 && IS_UIMM ($5, 3)))
            {
@@ -1595,16 +1685,20 @@ asm_1:
        }
        | CCREG ASSIGN REG _ASSIGN_ASSIGN REG
        {
        }
        | CCREG ASSIGN REG _ASSIGN_ASSIGN REG
        {
-         if (REG_CLASS($3) == REG_CLASS($5))
+         if ((IS_DREG ($3) && IS_DREG ($5))
+             || (IS_PREG ($3) && IS_PREG ($5)))
            {
              notethat ("CCflag: CC = dpregs == dpregs\n");
              $$ = CCFLAG (&$3, $5.regno & CODE_MASK, 0, 0, IS_PREG ($3) ? 1 : 0);
            }
          else
            {
              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");
+           return yyerror ("Bad register in comparison");
        }
        | CCREG ASSIGN REG _ASSIGN_ASSIGN expr
        {
        }
        | CCREG ASSIGN REG _ASSIGN_ASSIGN expr
        {
+         if (!IS_DREG ($3) && !IS_PREG ($3))
+           return yyerror ("Bad register in comparison");
+
          if (IS_IMM ($5, 3))
            {
              notethat ("CCflag: CC = dpregs == imm3\n");
          if (IS_IMM ($5, 3))
            {
              notethat ("CCflag: CC = dpregs == imm3\n");
@@ -1625,34 +1719,26 @@ asm_1:
        }
        | CCREG ASSIGN REG _LESS_THAN_ASSIGN REG iu_or_nothing
        {
        }
        | CCREG ASSIGN REG _LESS_THAN_ASSIGN REG iu_or_nothing
        {
-         if (REG_CLASS($3) == REG_CLASS($5))
+         if ((IS_DREG ($3) && IS_DREG ($5))
+             || (IS_PREG ($3) && IS_PREG ($5)))
            {
            {
-             notethat ("CCflag: CC = pregs <= pregs (..)\n");
+             notethat ("CCflag: CC = dpregs <= dpregs (..)\n");
              $$ = CCFLAG (&$3, $5.regno & CODE_MASK,
                           1 + $6.r0, 0, IS_PREG ($3) ? 1 : 0);
            }
          else
              $$ = CCFLAG (&$3, $5.regno & CODE_MASK,
                           1 + $6.r0, 0, IS_PREG ($3) ? 1 : 0);
            }
          else
-           return yyerror ("Compare only of same register class");
+           return yyerror ("Bad register in comparison");
        }
        | CCREG ASSIGN REG _LESS_THAN_ASSIGN expr iu_or_nothing
        {
        }
        | CCREG ASSIGN REG _LESS_THAN_ASSIGN expr iu_or_nothing
        {
+         if (!IS_DREG ($3) && !IS_PREG ($3))
+           return yyerror ("Bad register in comparison");
+
          if (($6.r0 == 1 && IS_IMM ($5, 3))
              || ($6.r0 == 3 && IS_UIMM ($5, 3)))
            {
          if (($6.r0 == 1 && IS_IMM ($5, 3))
              || ($6.r0 == 3 && IS_UIMM ($5, 3)))
            {
-             if (IS_DREG ($3))
-               {
-                 notethat ("CCflag: CC = dregs <= (u)imm3\n");
-                 /*    x       y     opc     I     G   */
-                 $$ = CCFLAG (&$3, imm3 ($5), 1 + $6.r0, 1, 0);
-               }
-             else if (IS_PREG ($3))
-               {
-                 notethat ("CCflag: CC = pregs <= (u)imm3\n");
-                 /*    x       y     opc     I     G   */
-                 $$ = CCFLAG (&$3, imm3 ($5), 1 + $6.r0, 1, 1);
-               }
-             else
-               return yyerror ("Dreg or Preg expected");
+             notethat ("CCflag: CC = dpregs <= (u)imm3\n");
+             $$ = CCFLAG (&$3, imm3 ($5), 1 + $6.r0, 1, IS_PREG ($3) ? 1 : 0);
            }
          else
            return yyerror ("Bad constant value");
            }
          else
            return yyerror ("Bad constant value");
@@ -1677,13 +1763,24 @@ asm_1:
 
        | REG ASSIGN REG
        {
 
        | REG ASSIGN REG
        {
-         if (IS_ALLREG ($1) && IS_ALLREG ($3))
+         if ((IS_GENREG ($1) && IS_GENREG ($3))
+             || (IS_GENREG ($1) && IS_DAGREG ($3))
+             || (IS_DAGREG ($1) && IS_GENREG ($3))
+             || (IS_DAGREG ($1) && IS_DAGREG ($3))
+             || (IS_GENREG ($1) && $3.regno == REG_USP)
+             || ($1.regno == REG_USP && IS_GENREG ($3))
+             || ($1.regno == REG_USP && $3.regno == REG_USP)
+             || (IS_DREG ($1) && IS_SYSREG ($3))
+             || (IS_PREG ($1) && IS_SYSREG ($3))
+             || (IS_SYSREG ($1) && IS_GENREG ($3))
+             || (IS_ALLREG ($1) && IS_EMUDAT ($3))
+             || (IS_EMUDAT ($1) && IS_ALLREG ($3))
+             || (IS_SYSREG ($1) && $3.regno == REG_USP))
            {
            {
-             notethat ("REGMV: allregs = allregs\n");
              $$ = bfin_gen_regmv (&$3, &$1);
            }
          else
              $$ = bfin_gen_regmv (&$3, &$1);
            }
          else
-           return yyerror ("Register mismatch");
+           return yyerror ("Unsupported register move");
        }
 
        | CCREG ASSIGN REG
        }
 
        | CCREG ASSIGN REG
@@ -1694,7 +1791,7 @@ asm_1:
              $$ = bfin_gen_cc2dreg (1, &$3);
            }
          else
              $$ = bfin_gen_cc2dreg (1, &$3);
            }
          else
-           return yyerror ("Register mismatch");
+           return yyerror ("Only 'CC = Dreg' supported");
        }
 
        | REG ASSIGN CCREG
        }
 
        | REG ASSIGN CCREG
@@ -1705,7 +1802,7 @@ asm_1:
              $$ = bfin_gen_cc2dreg (0, &$1);
            }
          else
              $$ = bfin_gen_cc2dreg (0, &$1);
            }
          else
-           return yyerror ("Register mismatch");
+           return yyerror ("Only 'Dreg = CC' supported");
        }
 
        | CCREG _ASSIGN_BANG CCREG
        }
 
        | CCREG _ASSIGN_BANG CCREG
@@ -1713,7 +1810,7 @@ asm_1:
          notethat ("CC2dreg: CC =! CC\n");
          $$ = bfin_gen_cc2dreg (3, 0);
        }
          notethat ("CC2dreg: CC =! CC\n");
          $$ = bfin_gen_cc2dreg (3, 0);
        }
-                       
+
 /* DSPMULT.  */
 
        | HALF_REG ASSIGN multiply_halfregs opt_mode
 /* DSPMULT.  */
 
        | HALF_REG ASSIGN multiply_halfregs opt_mode
@@ -1723,6 +1820,11 @@ asm_1:
          if (!IS_H ($1) && $4.MM)
            return yyerror ("(M) not allowed with MAC0");
 
          if (!IS_H ($1) && $4.MM)
            return yyerror ("(M) not allowed with MAC0");
 
+         if ($4.mod != 0 && $4.mod != M_FU && $4.mod != M_IS
+             && $4.mod != M_IU && $4.mod != M_T && $4.mod != M_TFU
+             && $4.mod != M_S2RND && $4.mod != M_ISS2 && $4.mod != M_IH)
+           return yyerror ("bad option.");
+
          if (IS_H ($1))
            {
              $$ = DSP32MULT (0, $4.MM, $4.mod, 1, 0,
          if (IS_H ($1))
            {
              $$ = DSP32MULT (0, $4.MM, $4.mod, 1, 0,
@@ -1732,12 +1834,12 @@ asm_1:
          else
            {
              $$ = DSP32MULT (0, 0, $4.mod, 0, 0,
          else
            {
              $$ = DSP32MULT (0, 0, $4.mod, 0, 0,
-                             0, 0, IS_H ($3.s0), IS_H ($3.s1), 
+                             0, 0, IS_H ($3.s0), IS_H ($3.s1),
                              &$1, 0, &$3.s0, &$3.s1, 1);
            }
        }
 
                              &$1, 0, &$3.s0, &$3.s1, 1);
            }
        }
 
-       | REG ASSIGN multiply_halfregs opt_mode 
+       | REG ASSIGN multiply_halfregs opt_mode
        {
          /* Odd registers can use (M).  */
          if (!IS_DREG ($1))
        {
          /* Odd registers can use (M).  */
          if (!IS_DREG ($1))
@@ -1746,6 +1848,10 @@ asm_1:
          if (IS_EVEN ($1) && $4.MM)
            return yyerror ("(M) not allowed with MAC0");
 
          if (IS_EVEN ($1) && $4.MM)
            return yyerror ("(M) not allowed with MAC0");
 
+         if ($4.mod != 0 && $4.mod != M_FU && $4.mod != M_IS
+             && $4.mod != M_S2RND && $4.mod != M_ISS2)
+           return yyerror ("bad option");
+
          if (!IS_EVEN ($1))
            {
              notethat ("dsp32mult: dregs = multiply_halfregs (opt_mode)\n");
          if (!IS_EVEN ($1))
            {
              notethat ("dsp32mult: dregs = multiply_halfregs (opt_mode)\n");
@@ -1758,7 +1864,7 @@ asm_1:
            {
              notethat ("dsp32mult: dregs = multiply_halfregs opt_mode\n");
              $$ = DSP32MULT (0, 0, $4.mod, 0, 1,
            {
              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), 
+                             0, 0, IS_H ($3.s0), IS_H ($3.s1),
                              &$1,  0, &$3.s0, &$3.s1, 1);
            }
        }
                              &$1,  0, &$3.s0, &$3.s1, 1);
            }
        }
@@ -1766,7 +1872,7 @@ asm_1:
        | HALF_REG ASSIGN multiply_halfregs opt_mode COMMA
           HALF_REG ASSIGN multiply_halfregs opt_mode
        {
        | HALF_REG ASSIGN multiply_halfregs opt_mode COMMA
           HALF_REG ASSIGN multiply_halfregs opt_mode
        {
-         if (!IS_DREG ($1) || !IS_DREG ($6)) 
+         if (!IS_DREG ($1) || !IS_DREG ($6))
            return yyerror ("Dregs expected");
 
          if (!IS_HCOMPL($1, $6))
            return yyerror ("Dregs expected");
 
          if (!IS_HCOMPL($1, $6))
@@ -1794,7 +1900,7 @@ asm_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)) 
+         if (!IS_DREG ($1) || !IS_DREG ($6))
            return yyerror ("Dregs expected");
 
          if ((IS_EVEN ($1) && $6.regno - $1.regno != 1)
            return yyerror ("Dregs expected");
 
          if ((IS_EVEN ($1) && $6.regno - $1.regno != 1)
@@ -1896,22 +2002,20 @@ asm_1:
          else
            return yyerror ("Bad shift value or register");
        }
          else
            return yyerror ("Bad shift value or register");
        }
-       | HALF_REG ASSIGN HALF_REG LESS_LESS expr
+       | HALF_REG ASSIGN HALF_REG LESS_LESS expr smod
        {
          if (IS_UIMM ($5, 4))
            {
        {
          if (IS_UIMM ($5, 4))
            {
-             notethat ("dsp32shiftimm: dregs_half = dregs_half << uimm4\n");
-             $$ = DSP32SHIFTIMM (0x0, &$1, imm5 ($5), &$3, 2, HL2 ($1, $3));
-           }
-         else
-           return yyerror ("Bad shift value");
-       }
-       | HALF_REG ASSIGN HALF_REG LESS_LESS expr smod 
-       {
-         if (IS_UIMM ($5, 4))
-           {
-             notethat ("dsp32shiftimm: dregs_half = dregs_half << uimm4\n");
-             $$ = DSP32SHIFTIMM (0x0, &$1, imm5 ($5), &$3, $6.s0, HL2 ($1, $3));
+             if ($6.s0)
+               {
+                 notethat ("dsp32shiftimm: dregs_half = dregs_half << uimm4 (S)\n");
+                 $$ = DSP32SHIFTIMM (0x0, &$1, imm5 ($5), &$3, $6.s0, HL2 ($1, $3));
+               }
+             else
+               {
+                 notethat ("dsp32shiftimm: dregs_half = dregs_half << uimm4\n");
+                 $$ = DSP32SHIFTIMM (0x0, &$1, imm5 ($5), &$3, 2, HL2 ($1, $3));
+               }
            }
          else
            return yyerror ("Bad shift value");
            }
          else
            return yyerror ("Bad shift value");
@@ -1930,7 +2034,7 @@ asm_1:
                }
              else
                {
                }
              else
                {
-                 
+
                  op = 2;
                  notethat ("dsp32shift: dregs = ASHIFT dregs BY dregs_lo (.)\n");
                }
                  op = 2;
                  notethat ("dsp32shift: dregs = ASHIFT dregs BY dregs_lo (.)\n");
                }
@@ -1993,7 +2097,7 @@ asm_1:
            return yyerror ("Register mismatch");
        }
 
            return yyerror ("Register mismatch");
        }
 
-       | REG ASSIGN EXTRACT LPAREN REG COMMA HALF_REG RPAREN xpmod 
+       | REG ASSIGN EXTRACT LPAREN REG COMMA HALF_REG RPAREN xpmod
        {
          if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG_L ($7))
            {
        {
          if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG_L ($7))
            {
@@ -2170,7 +2274,7 @@ asm_1:
            return yyerror ("Register mismatch");
        }
 
            return yyerror ("Register mismatch");
        }
 
-       | HALF_REG ASSIGN CCREG ASSIGN BXORSHIFT LPAREN REG_A COMMA REG RPAREN 
+       | HALF_REG ASSIGN CCREG ASSIGN BXORSHIFT LPAREN REG_A COMMA REG RPAREN
        {
          if (IS_DREG ($1)
              && $7.regno == REG_A0
        {
          if (IS_DREG ($1)
              && $7.regno == REG_A0
@@ -2229,7 +2333,7 @@ asm_1:
            return yyerror ("Register mismatch");
        }
 
            return yyerror ("Register mismatch");
        }
 
-       | a_assign ROT REG_A BY expr 
+       | a_assign ROT REG_A BY expr
        {
          if (IS_IMM ($5, 6))
            {
        {
          if (IS_IMM ($5, 6))
            {
@@ -2240,7 +2344,7 @@ asm_1:
            return yyerror ("Register mismatch");
        }
 
            return yyerror ("Register mismatch");
        }
 
-       | REG ASSIGN ROT REG BY expr 
+       | REG ASSIGN ROT REG BY expr
        {
          if (IS_DREG ($1) && IS_DREG ($4) && IS_IMM ($6, 6))
            {
        {
          if (IS_DREG ($1) && IS_DREG ($4) && IS_IMM ($6, 6))
            {
@@ -2282,9 +2386,9 @@ asm_1:
          else
            return yyerror ("Register mismatch");
        }
          else
            return yyerror ("Register mismatch");
        }
-       
+
        /* The ASR bit is just inverted here. */
        /* The ASR bit is just inverted here. */
-       | HALF_REG ASSIGN VIT_MAX LPAREN REG RPAREN asr_asl 
+       | HALF_REG ASSIGN VIT_MAX LPAREN REG RPAREN asr_asl
        {
          if (IS_DREG_L ($1) && IS_DREG ($5))
            {
        {
          if (IS_DREG_L ($1) && IS_DREG ($5))
            {
@@ -2295,7 +2399,7 @@ asm_1:
            return yyerror ("Register mismatch");
        }
 
            return yyerror ("Register mismatch");
        }
 
-       | REG ASSIGN VIT_MAX LPAREN REG COMMA REG RPAREN asr_asl 
+       | REG ASSIGN VIT_MAX LPAREN REG COMMA REG RPAREN asr_asl
        {
          if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
            {
        {
          if (IS_DREG ($1) && IS_DREG ($5) && IS_DREG ($7))
            {
@@ -2308,6 +2412,9 @@ asm_1:
 
        | BITMUX LPAREN REG COMMA REG COMMA REG_A RPAREN asr_asl
        {
 
        | BITMUX LPAREN REG COMMA REG COMMA REG_A RPAREN asr_asl
        {
+         if (REG_SAME ($3, $5))
+           return yyerror ("Illegal source register combination");
+
          if (IS_DREG ($3) && IS_DREG ($5) && !IS_A1 ($7))
            {
              notethat ("dsp32shift: BITMUX (dregs , dregs , A0) (ASR)\n");
          if (IS_DREG ($3) && IS_DREG ($5) && !IS_A1 ($7))
            {
              notethat ("dsp32shift: BITMUX (dregs , dregs , A0) (ASR)\n");
@@ -2601,6 +2708,9 @@ asm_1:
        {
          if (IS_PREG ($3))
            {
        {
          if (IS_PREG ($3))
            {
+             if ($3.regno == REG_SP || $3.regno == REG_FP)
+               return yyerror ("Bad register for TESTSET");
+
              notethat ("ProgCtrl: TESTSET (pregs )\n");
              $$ = PROGCTRL (11, $3.regno & CODE_MASK);
            }
              notethat ("ProgCtrl: TESTSET (pregs )\n");
              $$ = PROGCTRL (11, $3.regno & CODE_MASK);
            }
@@ -2887,76 +2997,105 @@ asm_1:
 
        | B LBRACK REG post_op RBRACK ASSIGN REG
        {
 
        | B LBRACK REG post_op RBRACK ASSIGN REG
        {
-         if (IS_PREG ($3) && IS_DREG ($7))
-           {
-             notethat ("LDST: B [ pregs <post_op> ] = dregs\n");
-             $$ = LDST (&$3, &$7, $4.x0, 2, 0, 1);
-           }
-         else
-           return yyerror ("Register mismatch");
+         if (!IS_DREG ($7))
+           return yyerror ("Dreg expected for source operand");
+         if (!IS_PREG ($3))
+           return yyerror ("Preg expected in address");
+
+         notethat ("LDST: B [ pregs <post_op> ] = dregs\n");
+         $$ = LDST (&$3, &$7, $4.x0, 2, 0, 1);
        }
 
 /* LDSTidxI:   B [ pregs + imm16 ] = dregs.  */
        | B LBRACK REG plus_minus expr RBRACK ASSIGN REG
        {
        }
 
 /* LDSTidxI:   B [ pregs + imm16 ] = dregs.  */
        | B LBRACK REG plus_minus expr RBRACK ASSIGN REG
        {
-         if (IS_PREG ($3) && IS_RANGE(16, $5, $4.r0, 1) && IS_DREG ($8))
+         Expr_Node *tmp = $5;
+
+         if (!IS_DREG ($8))
+           return yyerror ("Dreg expected for source operand");
+         if (!IS_PREG ($3))
+           return yyerror ("Preg expected in address");
+
+         if (IS_RELOC ($5))
+           return yyerror ("Plain symbol used as offset");
+
+         if ($4.r0)
+           tmp = unary (Expr_Op_Type_NEG, tmp);
+
+         if (in_range_p (tmp, -32768, 32767, 0))
            {
              notethat ("LDST: B [ pregs + imm16 ] = dregs\n");
            {
              notethat ("LDST: B [ pregs + imm16 ] = dregs\n");
-             if ($4.r0)
-               neg_value ($5);
              $$ = LDSTIDXI (&$3, &$8, 1, 2, 0, $5);
            }
          else
              $$ = LDSTIDXI (&$3, &$8, 1, 2, 0, $5);
            }
          else
-           return yyerror ("Register mismatch or const size wrong");
+           return yyerror ("Displacement out of range");
        }
 
 
 /* LDSTii:     W [ pregs + uimm4s2 ] = dregs.  */
        | W LBRACK REG plus_minus expr RBRACK ASSIGN REG
        {
        }
 
 
 /* LDSTii:     W [ pregs + uimm4s2 ] = dregs.  */
        | W LBRACK REG plus_minus expr RBRACK ASSIGN REG
        {
-         if (IS_PREG ($3) && IS_URANGE (4, $5, $4.r0, 2) && IS_DREG ($8))
+         Expr_Node *tmp = $5;
+
+         if (!IS_DREG ($8))
+           return yyerror ("Dreg expected for source operand");
+         if (!IS_PREG ($3))
+           return yyerror ("Preg expected in address");
+
+         if ($4.r0)
+           tmp = unary (Expr_Op_Type_NEG, tmp);
+
+         if (IS_RELOC ($5))
+           return yyerror ("Plain symbol used as offset");
+
+         if (in_range_p (tmp, 0, 30, 1))
            {
              notethat ("LDSTii: W [ pregs +- uimm5m2 ] = dregs\n");
            {
              notethat ("LDSTii: W [ pregs +- uimm5m2 ] = dregs\n");
-             $$ = LDSTII (&$3, &$8, $5, 1, 1);
+             $$ = LDSTII (&$3, &$8, tmp, 1, 1);
            }
            }
-         else if (IS_PREG ($3) && IS_RANGE(16, $5, $4.r0, 2) && IS_DREG ($8))
+         else if (in_range_p (tmp, -65536, 65535, 1))
            {
              notethat ("LDSTidxI: W [ pregs + imm17m2 ] = dregs\n");
            {
              notethat ("LDSTidxI: W [ pregs + imm17m2 ] = dregs\n");
-             if ($4.r0)
-               neg_value ($5);
-             $$ = LDSTIDXI (&$3, &$8, 1, 1, 0, $5);
+             $$ = LDSTIDXI (&$3, &$8, 1, 1, 0, tmp);
            }
          else
            }
          else
-           return yyerror ("Bad register(s) or wrong constant size");
+           return yyerror ("Displacement out of range");
        }
 
 /* LDST:       W [ pregs <post_op> ] = dregs.  */
        | W LBRACK REG post_op RBRACK ASSIGN REG
        {
        }
 
 /* LDST:       W [ pregs <post_op> ] = dregs.  */
        | W LBRACK REG post_op RBRACK ASSIGN REG
        {
-         if (IS_PREG ($3) && IS_DREG ($7))
-           {
-             notethat ("LDST: W [ pregs <post_op> ] = dregs\n");
-             $$ = LDST (&$3, &$7, $4.x0, 1, 0, 1);
-           }
-         else
-           return yyerror ("Bad register(s) for STORE");
+         if (!IS_DREG ($7))
+           return yyerror ("Dreg expected for source operand");
+         if (!IS_PREG ($3))
+           return yyerror ("Preg expected in address");
+
+         notethat ("LDST: W [ pregs <post_op> ] = dregs\n");
+         $$ = LDST (&$3, &$7, $4.x0, 1, 0, 1);
        }
 
        | W LBRACK REG post_op RBRACK ASSIGN HALF_REG
        {
        }
 
        | W LBRACK REG post_op RBRACK ASSIGN HALF_REG
        {
+         if (!IS_DREG ($7))
+           return yyerror ("Dreg expected for source operand");
+         if ($4.x0 == 2)
+           {
+             if (!IS_IREG ($3) && !IS_PREG ($3))
+               return yyerror ("Ireg or Preg expected in address");
+           }
+         else if (!IS_IREG ($3))
+           return yyerror ("Ireg expected in address");
+
          if (IS_IREG ($3))
            {
              notethat ("dspLDST: W [ iregs <post_op> ] = dregs_half\n");
              $$ = DSPLDST (&$3, 1 + IS_H ($7), &$7, $4.x0, 1);
            }
          if (IS_IREG ($3))
            {
              notethat ("dspLDST: W [ iregs <post_op> ] = dregs_half\n");
              $$ = DSPLDST (&$3, 1 + IS_H ($7), &$7, $4.x0, 1);
            }
-         else if ($4.x0 == 2 && IS_PREG ($3) && IS_DREG ($7))
+         else
            {
            {
-             notethat ("LDSTpmod: W [ pregs <post_op>] = dregs_half\n");
+             notethat ("LDSTpmod: W [ pregs ] = dregs_half\n");
              $$ = LDSTPMOD (&$3, &$7, &$3, 1 + IS_H ($7), 1);
              $$ = LDSTPMOD (&$3, &$7, &$3, 1 + IS_H ($7), 1);
-             
            }
            }
-         else
-           return yyerror ("Bad register(s) for STORE");
        }
 
 /* LDSTiiFP:   [ FP - const ] = dpregs.  */
        }
 
 /* LDSTiiFP:   [ FP - const ] = dpregs.  */
@@ -2966,14 +3105,17 @@ asm_1:
          int ispreg = IS_PREG ($7);
 
          if (!IS_PREG ($2))
          int ispreg = IS_PREG ($7);
 
          if (!IS_PREG ($2))
-           return yyerror ("Preg expected for indirect");
+           return yyerror ("Preg expected in address");
 
          if (!IS_DREG ($7) && !ispreg)
 
          if (!IS_DREG ($7) && !ispreg)
-           return yyerror ("Bad source register for STORE");
+           return yyerror ("Preg expected for source operand");
 
          if ($3.r0)
            tmp = unary (Expr_Op_Type_NEG, tmp);
 
 
          if ($3.r0)
            tmp = unary (Expr_Op_Type_NEG, tmp);
 
+         if (IS_RELOC ($4))
+           return yyerror ("Plain symbol used as offset");
+
          if (in_range_p (tmp, 0, 63, 3))
            {
              notethat ("LDSTii: dpregs = [ pregs + uimm6m4 ]\n");
          if (in_range_p (tmp, 0, 63, 3))
            {
              notethat ("LDSTii: dpregs = [ pregs + uimm6m4 ]\n");
@@ -2988,105 +3130,128 @@ asm_1:
          else if (in_range_p (tmp, -131072, 131071, 3))
            {
              notethat ("LDSTidxI: [ pregs + imm18m4 ] = dpregs\n");
          else if (in_range_p (tmp, -131072, 131071, 3))
            {
              notethat ("LDSTidxI: [ pregs + imm18m4 ] = dpregs\n");
-             $$ = LDSTIDXI (&$2, &$7, 1, 0, ispreg ? 1: 0, tmp);
+             $$ = LDSTIDXI (&$2, &$7, 1, 0, ispreg ? 1 : 0, tmp);
            }
          else
            }
          else
-           return yyerror ("Displacement out of range for store");
+           return yyerror ("Displacement out of range");
        }
 
        | REG ASSIGN W LBRACK REG plus_minus expr RBRACK xpmod
        {
        }
 
        | REG ASSIGN W LBRACK REG plus_minus expr RBRACK xpmod
        {
-         if (IS_DREG ($1) && IS_PREG ($5) && IS_URANGE (4, $7, $6.r0, 2))
+         Expr_Node *tmp = $7;
+         if (!IS_DREG ($1))
+           return yyerror ("Dreg expected for destination operand");
+         if (!IS_PREG ($5))
+           return yyerror ("Preg expected in address");
+
+         if ($6.r0)
+           tmp = unary (Expr_Op_Type_NEG, tmp);
+
+         if (IS_RELOC ($7))
+           return yyerror ("Plain symbol used as offset");
+
+         if (in_range_p (tmp, 0, 30, 1))
            {
            {
-             notethat ("LDSTii: dregs = W [ pregs + uimm4s2 ] (.)\n");
-             $$ = LDSTII (&$5, &$1, $7, 0, 1 << $9.r0);
+             notethat ("LDSTii: dregs = W [ pregs + uimm5m2 ] (.)\n");
+             $$ = LDSTII (&$5, &$1, tmp, 0, 1 << $9.r0);
            }
            }
-         else if (IS_DREG ($1) && IS_PREG ($5) && IS_RANGE(16, $7, $6.r0, 2))
+         else if (in_range_p (tmp, -65536, 65535, 1))
            {
              notethat ("LDSTidxI: dregs = W [ pregs + imm17m2 ] (.)\n");
            {
              notethat ("LDSTidxI: dregs = W [ pregs + imm17m2 ] (.)\n");
-             if ($6.r0)
-               neg_value ($7);
-             $$ = LDSTIDXI (&$5, &$1, 0, 1, $9.r0, $7);
+             $$ = LDSTIDXI (&$5, &$1, 0, 1, $9.r0, tmp);
            }
          else
            }
          else
-           return yyerror ("Bad register or constant for LOAD");
-       }       
+           return yyerror ("Displacement out of range");
+       }
 
        | HALF_REG ASSIGN W LBRACK REG post_op RBRACK
        {
 
        | HALF_REG ASSIGN W LBRACK REG post_op RBRACK
        {
+         if (!IS_DREG ($1))
+           return yyerror ("Dreg expected for source operand");
+         if ($6.x0 == 2)
+           {
+             if (!IS_IREG ($5) && !IS_PREG ($5))
+               return yyerror ("Ireg or Preg expected in address");
+           }
+         else if (!IS_IREG ($5))
+           return yyerror ("Ireg expected in address");
+
          if (IS_IREG ($5))
            {
          if (IS_IREG ($5))
            {
-             notethat ("dspLDST: dregs_half = W [ iregs ]\n");
+             notethat ("dspLDST: dregs_half = W [ iregs <post_op> ]\n");
              $$ = DSPLDST(&$5, 1 + IS_H ($1), &$1, $6.x0, 0);
            }
              $$ = DSPLDST(&$5, 1 + IS_H ($1), &$1, $6.x0, 0);
            }
-         else if ($6.x0 == 2 && IS_DREG ($1) && IS_PREG ($5))
+         else
            {
            {
-             notethat ("LDSTpmod: dregs_half = W [ pregs ]\n");
+             notethat ("LDSTpmod: dregs_half = W [ pregs <post_op> ]\n");
              $$ = LDSTPMOD (&$5, &$1, &$5, 1 + IS_H ($1), 0);
            }
              $$ = LDSTPMOD (&$5, &$1, &$5, 1 + IS_H ($1), 0);
            }
-         else
-           return yyerror ("Bad register or post_op for LOAD");
        }
 
 
        | REG ASSIGN W LBRACK REG post_op RBRACK xpmod
        {
        }
 
 
        | REG ASSIGN W LBRACK REG post_op RBRACK xpmod
        {
-         if (IS_DREG ($1) && IS_PREG ($5))
-           {
-             notethat ("LDST: dregs = W [ pregs <post_op> ] (.)\n");
-             $$ = LDST (&$5, &$1, $6.x0, 1, $8.r0, 0);
-           }
-         else
-           return yyerror ("Bad register for LOAD");
+         if (!IS_DREG ($1))
+           return yyerror ("Dreg expected for destination operand");
+         if (!IS_PREG ($5))
+           return yyerror ("Preg expected in address");
+
+         notethat ("LDST: dregs = W [ pregs <post_op> ] (.)\n");
+         $$ = LDST (&$5, &$1, $6.x0, 1, $8.r0, 0);
        }
 
        | REG ASSIGN W LBRACK REG _PLUS_PLUS REG RBRACK xpmod
        {
        }
 
        | REG ASSIGN W LBRACK REG _PLUS_PLUS REG RBRACK xpmod
        {
-         if (IS_DREG ($1) && IS_PREG ($5) && IS_PREG ($7))
-           {
-             notethat ("LDSTpmod: dregs = W [ pregs ++ pregs ] (.)\n");
-             $$ = LDSTPMOD (&$5, &$1, &$7, 3, $9.r0);
-           }
-         else
-           return yyerror ("Bad register for LOAD");
+         if (!IS_DREG ($1))
+           return yyerror ("Dreg expected for destination operand");
+         if (!IS_PREG ($5) || !IS_PREG ($7))
+           return yyerror ("Preg expected in address");
+
+         notethat ("LDSTpmod: dregs = W [ pregs ++ pregs ] (.)\n");
+         $$ = LDSTPMOD (&$5, &$1, &$7, 3, $9.r0);
        }
 
        | HALF_REG ASSIGN W LBRACK REG _PLUS_PLUS REG RBRACK
        {
        }
 
        | HALF_REG ASSIGN W LBRACK REG _PLUS_PLUS REG RBRACK
        {
-         if (IS_DREG ($1) && IS_PREG ($5) && IS_PREG ($7))
-           {
-             notethat ("LDSTpmod: dregs_half = W [ pregs ++ pregs ]\n");
-             $$ = LDSTPMOD (&$5, &$1, &$7, 1 + IS_H ($1), 0);
-           }
-         else
-           return yyerror ("Bad register for LOAD");
+         if (!IS_DREG ($1))
+           return yyerror ("Dreg expected for destination operand");
+         if (!IS_PREG ($5) || !IS_PREG ($7))
+           return yyerror ("Preg expected in address");
+
+         notethat ("LDSTpmod: dregs_half = W [ pregs ++ pregs ]\n");
+         $$ = LDSTPMOD (&$5, &$1, &$7, 1 + IS_H ($1), 0);
        }
 
        | LBRACK REG post_op RBRACK ASSIGN REG
        {
        }
 
        | LBRACK REG post_op RBRACK ASSIGN REG
        {
-         if (IS_IREG ($2) && IS_DREG ($6))
+         if (!IS_IREG ($2) && !IS_PREG ($2))
+           return yyerror ("Ireg or Preg expected in address");
+         else if (IS_IREG ($2) && !IS_DREG ($6))
+           return yyerror ("Dreg expected for source operand");
+         else if (IS_PREG ($2) && !IS_DREG ($6) && !IS_PREG ($6))
+           return yyerror ("Dreg or Preg expected for source operand");
+
+         if (IS_IREG ($2))
            {
              notethat ("dspLDST: [ iregs <post_op> ] = dregs\n");
              $$ = DSPLDST(&$2, 0, &$6, $3.x0, 1);
            }
            {
              notethat ("dspLDST: [ iregs <post_op> ] = dregs\n");
              $$ = DSPLDST(&$2, 0, &$6, $3.x0, 1);
            }
-         else if (IS_PREG ($2) && IS_DREG ($6))
+         else if (IS_DREG ($6))
            {
              notethat ("LDST: [ pregs <post_op> ] = dregs\n");
              $$ = LDST (&$2, &$6, $3.x0, 0, 0, 1);
            }
            {
              notethat ("LDST: [ pregs <post_op> ] = dregs\n");
              $$ = LDST (&$2, &$6, $3.x0, 0, 0, 1);
            }
-         else if (IS_PREG ($2) && IS_PREG ($6))
+         else
            {
              notethat ("LDST: [ pregs <post_op> ] = pregs\n");
              $$ = LDST (&$2, &$6, $3.x0, 0, 1, 1);
            }
            {
              notethat ("LDST: [ pregs <post_op> ] = pregs\n");
              $$ = LDST (&$2, &$6, $3.x0, 0, 1, 1);
            }
-         else
-           return yyerror ("Bad register for STORE");
        }
 
        | LBRACK REG _PLUS_PLUS REG RBRACK ASSIGN REG
        {
        }
 
        | LBRACK REG _PLUS_PLUS REG RBRACK ASSIGN REG
        {
-         if (! IS_DREG ($7))
-           return yyerror ("Expected Dreg for last argument");
+         if (!IS_DREG ($7))
+           return yyerror ("Dreg expected for source operand");
 
          if (IS_IREG ($2) && IS_MREG ($4))
            {
 
          if (IS_IREG ($2) && IS_MREG ($4))
            {
@@ -3099,62 +3264,76 @@ asm_1:
              $$ = LDSTPMOD (&$2, &$7, &$4, 0, 1);
            }
          else
              $$ = LDSTPMOD (&$2, &$7, &$4, 0, 1);
            }
          else
-           return yyerror ("Bad register for STORE");
+           return yyerror ("Preg ++ Preg or Ireg ++ Mreg expected in address");
        }
        }
-                       
+
        | W LBRACK REG _PLUS_PLUS REG RBRACK ASSIGN HALF_REG
        {
          if (!IS_DREG ($8))
        | W LBRACK REG _PLUS_PLUS REG RBRACK ASSIGN HALF_REG
        {
          if (!IS_DREG ($8))
-           return yyerror ("Expect Dreg as last argument");
+           return yyerror ("Dreg expected for source operand");
+
          if (IS_PREG ($3) && IS_PREG ($5))
            {
              notethat ("LDSTpmod: W [ pregs ++ pregs ] = dregs_half\n");
              $$ = LDSTPMOD (&$3, &$8, &$5, 1 + IS_H ($8), 1);
            }
          else
          if (IS_PREG ($3) && IS_PREG ($5))
            {
              notethat ("LDSTpmod: W [ pregs ++ pregs ] = dregs_half\n");
              $$ = LDSTPMOD (&$3, &$8, &$5, 1 + IS_H ($8), 1);
            }
          else
-           return yyerror ("Bad register for STORE");
+           return yyerror ("Preg ++ Preg expected in address");
        }
 
        | REG ASSIGN B LBRACK REG plus_minus expr RBRACK xpmod
        {
        }
 
        | REG ASSIGN B LBRACK REG plus_minus expr RBRACK xpmod
        {
-         if (IS_DREG ($1) && IS_PREG ($5) && IS_RANGE(16, $7, $6.r0, 1))
+         Expr_Node *tmp = $7;
+         if (!IS_DREG ($1))
+           return yyerror ("Dreg expected for destination operand");
+         if (!IS_PREG ($5))
+           return yyerror ("Preg expected in address");
+
+         if ($6.r0)
+           tmp = unary (Expr_Op_Type_NEG, tmp);
+
+         if (IS_RELOC ($7))
+           return yyerror ("Plain symbol used as offset");
+
+         if (in_range_p (tmp, -32768, 32767, 0))
            {
              notethat ("LDSTidxI: dregs = B [ pregs + imm16 ] (%c)\n",
                       $9.r0 ? 'X' : 'Z');
            {
              notethat ("LDSTidxI: dregs = B [ pregs + imm16 ] (%c)\n",
                       $9.r0 ? 'X' : 'Z');
-             if ($6.r0)
-               neg_value ($7);
-             $$ = LDSTIDXI (&$5, &$1, 0, 2, $9.r0, $7);
+             $$ = LDSTIDXI (&$5, &$1, 0, 2, $9.r0, tmp);
            }
          else
            }
          else
-           return yyerror ("Bad register or value for LOAD");
+           return yyerror ("Displacement out of range");
        }
 
        | REG ASSIGN B LBRACK REG post_op RBRACK xpmod
        {
        }
 
        | REG ASSIGN B LBRACK REG post_op RBRACK xpmod
        {
-         if (IS_DREG ($1) && IS_PREG ($5))
-           {
-             notethat ("LDST: dregs = B [ pregs <post_op> ] (%c)\n",
-                      $8.r0 ? 'X' : 'Z');
-             $$ = LDST (&$5, &$1, $6.x0, 2, $8.r0, 0);
-           }
-         else
-           return yyerror ("Bad register for LOAD");
+         if (!IS_DREG ($1))
+           return yyerror ("Dreg expected for destination operand");
+         if (!IS_PREG ($5))
+           return yyerror ("Preg expected in address");
+
+         notethat ("LDST: dregs = B [ pregs <post_op> ] (%c)\n",
+                   $8.r0 ? 'X' : 'Z');
+         $$ = LDST (&$5, &$1, $6.x0, 2, $8.r0, 0);
        }
        }
-                       
+
        | REG ASSIGN LBRACK REG _PLUS_PLUS REG RBRACK
        {
        | REG ASSIGN LBRACK REG _PLUS_PLUS REG RBRACK
        {
-         if (IS_DREG ($1) && IS_IREG ($4) && IS_MREG ($6))
+         if (!IS_DREG ($1))
+           return yyerror ("Dreg expected for destination operand");
+
+         if (IS_IREG ($4) && IS_MREG ($6))
            {
              notethat ("dspLDST: dregs = [ iregs ++ mregs ]\n");
              $$ = DSPLDST(&$4, $6.regno & CODE_MASK, &$1, 3, 0);
            }
            {
              notethat ("dspLDST: dregs = [ iregs ++ mregs ]\n");
              $$ = DSPLDST(&$4, $6.regno & CODE_MASK, &$1, 3, 0);
            }
-         else if (IS_DREG ($1) && IS_PREG ($4) && IS_PREG ($6))
+         else if (IS_PREG ($4) && IS_PREG ($6))
            {
              notethat ("LDSTpmod: dregs = [ pregs ++ pregs ]\n");
              $$ = LDSTPMOD (&$4, &$1, &$6, 0, 0);
            }
          else
            {
              notethat ("LDSTpmod: dregs = [ pregs ++ pregs ]\n");
              $$ = LDSTPMOD (&$4, &$1, &$6, 0, 0);
            }
          else
-           return yyerror ("Bad register for LOAD");
+           return yyerror ("Preg ++ Preg or Ireg ++ Mreg expected in address");
        }
 
        | REG ASSIGN LBRACK REG plus_minus got_or_expr RBRACK
        }
 
        | REG ASSIGN LBRACK REG plus_minus got_or_expr RBRACK
@@ -3164,18 +3343,24 @@ asm_1:
          int isgot = IS_RELOC($6);
 
          if (!IS_PREG ($4))
          int isgot = IS_RELOC($6);
 
          if (!IS_PREG ($4))
-           return yyerror ("Preg expected for indirect");
+           return yyerror ("Preg expected in address");
 
          if (!IS_DREG ($1) && !ispreg)
 
          if (!IS_DREG ($1) && !ispreg)
-           return yyerror ("Bad destination register for LOAD");
+           return yyerror ("Dreg or Preg expected for destination operand");
+
+         if (tmp->type == Expr_Node_Reloc
+             && strcmp (tmp->value.s_value,
+                        "_current_shared_library_p5_offset_") != 0)
+           return yyerror ("Plain symbol used as offset");
 
          if ($5.r0)
            tmp = unary (Expr_Op_Type_NEG, tmp);
 
 
          if ($5.r0)
            tmp = unary (Expr_Op_Type_NEG, tmp);
 
-         if(isgot){
+         if (isgot)
+           {
              notethat ("LDSTidxI: dpregs = [ pregs + sym@got ]\n");
              notethat ("LDSTidxI: dpregs = [ pregs + sym@got ]\n");
-             $$ = LDSTIDXI (&$4, &$1, 0, 0, ispreg ? 1: 0, tmp);
-         }
+             $$ = LDSTIDXI (&$4, &$1, 0, 0, ispreg ? 1 : 0, tmp);
+           }
          else if (in_range_p (tmp, 0, 63, 3))
            {
              notethat ("LDSTii: dpregs = [ pregs + uimm7m4 ]\n");
          else if (in_range_p (tmp, 0, 63, 3))
            {
              notethat ("LDSTii: dpregs = [ pregs + uimm7m4 ]\n");
@@ -3190,26 +3375,34 @@ asm_1:
          else if (in_range_p (tmp, -131072, 131071, 3))
            {
              notethat ("LDSTidxI: dpregs = [ pregs + imm18m4 ]\n");
          else if (in_range_p (tmp, -131072, 131071, 3))
            {
              notethat ("LDSTidxI: dpregs = [ pregs + imm18m4 ]\n");
-             $$ = LDSTIDXI (&$4, &$1, 0, 0, ispreg ? 1: 0, tmp);
-             
+             $$ = LDSTIDXI (&$4, &$1, 0, 0, ispreg ? 1 : 0, tmp);
+
            }
          else
            }
          else
-           return yyerror ("Displacement out of range for load");
+           return yyerror ("Displacement out of range");
        }
 
        | REG ASSIGN LBRACK REG post_op RBRACK
        {
        }
 
        | REG ASSIGN LBRACK REG post_op RBRACK
        {
-         if (IS_DREG ($1) && IS_IREG ($4))
+         if (!IS_IREG ($4) && !IS_PREG ($4))
+           return yyerror ("Ireg or Preg expected in address");
+         else if (IS_IREG ($4) && !IS_DREG ($1))
+           return yyerror ("Dreg expected in destination operand");
+         else if (IS_PREG ($4) && !IS_DREG ($1) && !IS_PREG ($1)
+                  && ($4.regno != REG_SP || !IS_ALLREG ($1) || $5.x0 != 0))
+           return yyerror ("Dreg or Preg expected in destination operand");
+
+         if (IS_IREG ($4))
            {
              notethat ("dspLDST: dregs = [ iregs <post_op> ]\n");
              $$ = DSPLDST (&$4, 0, &$1, $5.x0, 0);
            }
            {
              notethat ("dspLDST: dregs = [ iregs <post_op> ]\n");
              $$ = DSPLDST (&$4, 0, &$1, $5.x0, 0);
            }
-         else if (IS_DREG ($1) && IS_PREG ($4))
+         else if (IS_DREG ($1))
            {
              notethat ("LDST: dregs = [ pregs <post_op> ]\n");
              $$ = LDST (&$4, &$1, $5.x0, 0, 0, 0);
            }
            {
              notethat ("LDST: dregs = [ pregs <post_op> ]\n");
              $$ = LDST (&$4, &$1, $5.x0, 0, 0, 0);
            }
-         else if (IS_PREG ($1) && IS_PREG ($4))
+         else if (IS_PREG ($1))
            {
              if (REG_SAME ($1, $4) && $5.x0 != 2)
                return yyerror ("Pregs can't be same");
            {
              if (REG_SAME ($1, $4) && $5.x0 != 2)
                return yyerror ("Pregs can't be same");
@@ -3217,13 +3410,11 @@ asm_1:
              notethat ("LDST: pregs = [ pregs <post_op> ]\n");
              $$ = LDST (&$4, &$1, $5.x0, 0, 1, 0);
            }
              notethat ("LDST: pregs = [ pregs <post_op> ]\n");
              $$ = LDST (&$4, &$1, $5.x0, 0, 1, 0);
            }
-         else if ($4.regno == REG_SP && IS_ALLREG ($1) && $5.x0 == 0)
+         else
            {
              notethat ("PushPopReg: allregs = [ SP ++ ]\n");
              $$ = PUSHPOPREG (&$1, 0);
            }
            {
              notethat ("PushPopReg: allregs = [ SP ++ ]\n");
              $$ = PUSHPOPREG (&$1, 0);
            }
-         else
-           return yyerror ("Bad register or value");
        }
 
 
        }
 
 
@@ -3319,7 +3510,7 @@ asm_1:
          else
            return yyerror ("Bad constant for LINK");
        }
          else
            return yyerror ("Bad constant for LINK");
        }
-               
+
        | UNLINK
        {
                notethat ("linkage: UNLINK\n");
        | UNLINK
        {
                notethat ("linkage: UNLINK\n");
@@ -3338,7 +3529,7 @@ asm_1:
            }
          else
            return yyerror ("Bad register or values for LSETUP");
            }
          else
            return yyerror ("Bad register or values for LSETUP");
-         
+
        }
        | LSETUP LPAREN expr COMMA expr RPAREN REG ASSIGN REG
        {
        }
        | LSETUP LPAREN expr COMMA expr RPAREN REG ASSIGN REG
        {
@@ -3355,7 +3546,7 @@ asm_1:
        | LSETUP LPAREN expr COMMA expr RPAREN REG ASSIGN REG GREATER_GREATER expr
        {
          if (IS_PCREL4 ($3) && IS_LPPCREL10 ($5)
        | LSETUP LPAREN expr COMMA expr RPAREN REG ASSIGN REG GREATER_GREATER expr
        {
          if (IS_PCREL4 ($3) && IS_LPPCREL10 ($5)
-             && IS_PREG ($9) && IS_CREG ($7) 
+             && IS_PREG ($9) && IS_CREG ($7)
              && EXPR_VALUE ($11) == 1)
            {
              notethat ("LoopSetup: LSETUP (pcrel4 , lppcrel10 ) counters = pregs >> 1\n");
              && EXPR_VALUE ($11) == 1)
            {
              notethat ("LoopSetup: LSETUP (pcrel4 , lppcrel10 ) counters = pregs >> 1\n");
@@ -3394,8 +3585,57 @@ asm_1:
          else
            return yyerror ("Bad register or values for LOOP");
        }
          else
            return yyerror ("Bad register or values for LOOP");
        }
+
+/* LOOP_BEGIN.  */
+       | LOOP_BEGIN NUMBER
+       {
+         Expr_Node_Value val;
+         val.i_value = $2;
+         Expr_Node *tmp = Expr_Node_Create (Expr_Node_Constant, val, NULL, NULL);
+         bfin_loop_attempt_create_label (tmp, 1);
+         if (!IS_RELOC (tmp))
+           return yyerror ("Invalid expression in LOOP_BEGIN statement");
+         bfin_loop_beginend (tmp, 1);
+         $$ = 0;
+       }
+       | LOOP_BEGIN expr
+       {
+         if (!IS_RELOC ($2))
+           return yyerror ("Invalid expression in LOOP_BEGIN statement");
+
+         bfin_loop_beginend ($2, 1);
+         $$ = 0;
+       }
+
+/* LOOP_END.  */
+       | LOOP_END NUMBER
+       {
+         Expr_Node_Value val;
+         val.i_value = $2;
+         Expr_Node *tmp = Expr_Node_Create (Expr_Node_Constant, val, NULL, NULL);
+         bfin_loop_attempt_create_label (tmp, 1);
+         if (!IS_RELOC (tmp))
+           return yyerror ("Invalid expression in LOOP_END statement");
+         bfin_loop_beginend (tmp, 0);
+         $$ = 0;
+       }
+       | LOOP_END expr
+       {
+         if (!IS_RELOC ($2))
+           return yyerror ("Invalid expression in LOOP_END statement");
+
+         bfin_loop_beginend ($2, 0);
+         $$ = 0;
+       }
+
 /* pseudoDEBUG.  */
 
 /* pseudoDEBUG.  */
 
+       | ABORT
+       {
+         notethat ("psedoDEBUG: ABORT\n");
+         $$ = bfin_gen_pseudodbg (3, 3, 0);
+       }
+
        | DBG
        {
          notethat ("pseudoDEBUG: DBG\n");
        | DBG
        {
          notethat ("pseudoDEBUG: DBG\n");
@@ -3409,7 +3649,7 @@ asm_1:
        | DBG REG
        {
          notethat ("pseudoDEBUG: DBG allregs\n");
        | DBG REG
        {
          notethat ("pseudoDEBUG: DBG allregs\n");
-         $$ = bfin_gen_pseudodbg (0, $2.regno & CODE_MASK, $2.regno & CLASS_MASK);
+         $$ = bfin_gen_pseudodbg (0, $2.regno & CODE_MASK, ($2.regno & CLASS_MASK) >> 4);
        }
 
        | DBGCMPLX LPAREN REG RPAREN
        }
 
        | DBGCMPLX LPAREN REG RPAREN
@@ -3417,33 +3657,54 @@ asm_1:
          if (!IS_DREG ($3))
            return yyerror ("Dregs expected");
          notethat ("pseudoDEBUG: DBGCMPLX (dregs )\n");
          if (!IS_DREG ($3))
            return yyerror ("Dregs expected");
          notethat ("pseudoDEBUG: DBGCMPLX (dregs )\n");
-         $$ = bfin_gen_pseudodbg (3, 6, $3.regno & CODE_MASK);
+         $$ = bfin_gen_pseudodbg (3, 6, ($3.regno & CODE_MASK) >> 4);
        }
        }
-       
+
        | DBGHALT
        {
          notethat ("psedoDEBUG: DBGHALT\n");
          $$ = bfin_gen_pseudodbg (3, 5, 0);
        }
 
        | DBGHALT
        {
          notethat ("psedoDEBUG: DBGHALT\n");
          $$ = bfin_gen_pseudodbg (3, 5, 0);
        }
 
+       | HLT
+       {
+         notethat ("psedoDEBUG: HLT\n");
+         $$ = bfin_gen_pseudodbg (3, 4, 0);
+       }
+
        | DBGA LPAREN HALF_REG COMMA expr RPAREN
        {
        | DBGA LPAREN HALF_REG COMMA expr RPAREN
        {
-         notethat ("pseudodbg_assert: DBGA (dregs_lo , uimm16 )\n");
+         notethat ("pseudodbg_assert: DBGA (regs_lo/hi , uimm16 )\n");
          $$ = bfin_gen_pseudodbg_assert (IS_H ($3), &$3, uimm16 ($5));
        }
          $$ = bfin_gen_pseudodbg_assert (IS_H ($3), &$3, uimm16 ($5));
        }
-               
+
        | DBGAH LPAREN REG COMMA expr RPAREN
        {
        | DBGAH LPAREN REG COMMA expr RPAREN
        {
-         notethat ("pseudodbg_assert: DBGAH (dregs , uimm16 )\n");
+         notethat ("pseudodbg_assert: DBGAH (regs , uimm16 )\n");
          $$ = bfin_gen_pseudodbg_assert (3, &$3, uimm16 ($5));
        }
 
        | DBGAL LPAREN REG COMMA expr RPAREN
        {
          $$ = bfin_gen_pseudodbg_assert (3, &$3, uimm16 ($5));
        }
 
        | DBGAL LPAREN REG COMMA expr RPAREN
        {
-         notethat ("psedodbg_assert: DBGAL (dregs , uimm16 )\n");
+         notethat ("psedodbg_assert: DBGAL (regs , uimm16 )\n");
          $$ = bfin_gen_pseudodbg_assert (2, &$3, uimm16 ($5));
        }
 
          $$ = bfin_gen_pseudodbg_assert (2, &$3, uimm16 ($5));
        }
 
+       | OUTC expr
+       {
+         if (!IS_UIMM ($2, 8))
+           return yyerror ("Constant out of range");
+         notethat ("psedodbg_assert: OUTC uimm8\n");
+         $$ = bfin_gen_pseudochr (uimm8 ($2));
+       }
+
+       | OUTC REG
+       {
+         if (!IS_DREG ($2))
+           return yyerror ("Dregs expected");
+         notethat ("psedodbg_assert: OUTC dreg\n");
+         $$ = bfin_gen_pseudodbg (2, $2.regno & CODE_MASK, 0);
+       }
 
 ;
 
 
 ;
 
@@ -3517,7 +3778,7 @@ sco:
        $$.x0 = 1;
        }
        | SCO
        $$.x0 = 1;
        }
        | SCO
-       {       
+       {
        $$.s0 = 1;
        $$.x0 = 1;
        }
        $$.s0 = 1;
        $$.x0 = 1;
        }
@@ -3807,7 +4068,7 @@ min_max:
        $$.r0 = 0;
        }
        ;
        $$.r0 = 0;
        }
        ;
+
 op_bar_op:
        _PLUS_BAR_PLUS
        {
 op_bar_op:
        _PLUS_BAR_PLUS
        {
@@ -3928,8 +4189,8 @@ b3_op:
 post_op:
        {
        $$.x0 = 2;
 post_op:
        {
        $$.x0 = 2;
-       } 
-       | _PLUS_PLUS 
+       }
+       | _PLUS_PLUS
        {
        $$.x0 = 0;
        }
        {
        $$.x0 = 0;
        }
@@ -3965,6 +4226,11 @@ a_plusassign:
 assign_macfunc:
        REG ASSIGN REG_A
        {
 assign_macfunc:
        REG ASSIGN REG_A
        {
+         if (IS_A1 ($3) && IS_EVEN ($1))
+           return yyerror ("Cannot move A1 to even register");
+         else if (!IS_A1 ($3) && !IS_EVEN ($1))
+           return yyerror ("Cannot move A0 to odd register");
+
          $$.w = 1;
           $$.P = 1;
           $$.n = IS_A1 ($3);
          $$.w = 1;
           $$.P = 1;
           $$.n = IS_A1 ($3);
@@ -3972,11 +4238,6 @@ assign_macfunc:
           $$.dst = $1;
          $$.s0.regno = 0;
           $$.s1.regno = 0;
           $$.dst = $1;
          $$.s0.regno = 0;
           $$.s1.regno = 0;
-
-         if (IS_A1 ($3) && IS_EVEN ($1))
-           return yyerror ("Cannot move A1 to even register");
-         else if (!IS_A1 ($3) && !IS_EVEN ($1))
-           return yyerror ("Cannot move A0 to odd register");
        }
        | a_macfunc
        {
        }
        | a_macfunc
        {
@@ -3986,6 +4247,11 @@ assign_macfunc:
        }
        | REG ASSIGN LPAREN a_macfunc RPAREN
        {
        }
        | REG ASSIGN LPAREN a_macfunc RPAREN
        {
+         if ($4.n && IS_EVEN ($1))
+           return yyerror ("Cannot move A1 to even register");
+         else if (!$4.n && !IS_EVEN ($1))
+           return yyerror ("Cannot move A0 to odd register");
+
          $$ = $4;
          $$.w = 1;
           $$.P = 1;
          $$ = $4;
          $$.w = 1;
           $$.P = 1;
@@ -3994,6 +4260,11 @@ assign_macfunc:
 
        | HALF_REG ASSIGN LPAREN a_macfunc RPAREN
        {
 
        | HALF_REG ASSIGN LPAREN a_macfunc RPAREN
        {
+         if ($4.n && !IS_H ($1))
+           return yyerror ("Cannot move A1 to low half of register");
+         else if (!$4.n && IS_H ($1))
+           return yyerror ("Cannot move A0 to high half of register");
+
          $$ = $4;
          $$.w = 1;
          $$.P = 0;
          $$ = $4;
          $$.w = 1;
          $$.P = 0;
@@ -4002,6 +4273,11 @@ assign_macfunc:
 
        | HALF_REG ASSIGN REG_A
        {
 
        | HALF_REG ASSIGN REG_A
        {
+         if (IS_A1 ($3) && !IS_H ($1))
+           return yyerror ("Cannot move A1 to low half of register");
+         else if (!IS_A1 ($3) && IS_H ($1))
+           return yyerror ("Cannot move A0 to high half of register");
+
          $$.w = 1;
          $$.P = 0;
          $$.n = IS_A1 ($3);
          $$.w = 1;
          $$.P = 0;
          $$.n = IS_A1 ($3);
@@ -4009,11 +4285,6 @@ assign_macfunc:
           $$.dst = $1;
          $$.s0.regno = 0;
           $$.s1.regno = 0;
           $$.dst = $1;
          $$.s0.regno = 0;
           $$.s1.regno = 0;
-
-         if (IS_A1 ($3) && !IS_H ($1))
-           return yyerror ("Cannot move A1 to low half of register");
-         else if (!IS_A1 ($3) && IS_H ($1))
-           return yyerror ("Cannot move A0 to high half of register");
        }
        ;
 
        }
        ;
 
@@ -4076,27 +4347,27 @@ cc_op:
 ccstat:
        CCREG cc_op STATUS_REG
        {
 ccstat:
        CCREG cc_op STATUS_REG
        {
-       $$.r0 = $3.regno;
-       $$.x0 = $2.r0;
-       $$.s0 = 0;
+         $$.r0 = $3.regno;
+         $$.x0 = $2.r0;
+         $$.s0 = 0;
        }
        | CCREG cc_op V
        {
        }
        | CCREG cc_op V
        {
-       $$.r0 = 0x18;
-       $$.x0 = $2.r0;
-       $$.s0 = 0;
+         $$.r0 = 0x18;
+         $$.x0 = $2.r0;
+         $$.s0 = 0;
        }
        | STATUS_REG cc_op CCREG
        {
        }
        | STATUS_REG cc_op CCREG
        {
-       $$.r0 = $1.regno;
-       $$.x0 = $2.r0;
-       $$.s0 = 1;
+         $$.r0 = $1.regno;
+         $$.x0 = $2.r0;
+         $$.s0 = 1;
        }
        | V cc_op CCREG
        {
        }
        | V cc_op CCREG
        {
-       $$.r0 = 0x18;
-       $$.x0 = $2.r0;
-       $$.s0 = 1;
+         $$.r0 = 0x18;
+         $$.x0 = $2.r0;
+         $$.s0 = 1;
        }
        ;
 
        }
        ;
 
@@ -4196,7 +4467,7 @@ expr_1: expr_1 STAR expr_1
        }
        | expr_1 LESS_LESS expr_1
        {
        }
        | expr_1 LESS_LESS expr_1
        {
-       $$ = binary (Expr_Op_Type_Lshift, $1, $3);      
+       $$ = binary (Expr_Op_Type_Lshift, $1, $3);
        }
        | expr_1 GREATER_GREATER expr_1
        {
        }
        | expr_1 GREATER_GREATER expr_1
        {
@@ -4214,7 +4485,7 @@ expr_1: expr_1 STAR expr_1
        {
        $$ = binary (Expr_Op_Type_BOR, $1, $3);
        }
        {
        $$ = binary (Expr_Op_Type_BOR, $1, $3);
        }
-       | eterm 
+       | eterm
        {
        $$ = $1;
        }
        {
        $$ = $1;
        }
@@ -4233,17 +4504,17 @@ mkexpr (int x, SYMBOL_T s)
 }
 
 static int
 }
 
 static int
-value_match (Expr_Node *expr, int sz, int sign, int mul, int issigned)
+value_match (Expr_Node *exp, int sz, int sign, int mul, int issigned)
 {
 {
-  long umax = (1L << sz) - 1;
-  long min = -1L << (sz - 1);
-  long max = (1L << (sz - 1)) - 1;
-       
-  long v = EXPR_VALUE (expr);
+  int umax = (1 << sz) - 1;
+  int min = -1 << (sz - 1);
+  int max = (1 << (sz - 1)) - 1;
+
+  int v = (EXPR_VALUE (exp)) & 0xffffffff;
 
   if ((v % mul) != 0)
     {
 
   if ((v % mul) != 0)
     {
-      error ("%s:%d: Value Error -- Must align to %d\n", __FILE__, __LINE__, mul); 
+      error ("%s:%d: Value Error -- Must align to %d\n", __FILE__, __LINE__, mul);
       return 0;
     }
 
       return 0;
     }
 
@@ -4261,7 +4532,7 @@ value_match (Expr_Node *expr, int sz, int sign, int mul, int issigned)
 #endif
       return 0;
     }
 #endif
       return 0;
     }
-  if (v <= umax && v >= 0) 
+  if (v <= umax && v >= 0)
     return 1;
 #ifdef DEBUG
   fprintf(stderr, "unsigned value %lx out of range\n", v * mul);
     return 1;
 #ifdef DEBUG
   fprintf(stderr, "unsigned value %lx out of range\n", v * mul);
@@ -4280,48 +4551,48 @@ binary (Expr_Op_Type op, Expr_Node *x, Expr_Node *y)
     {
       switch (op)
        {
     {
       switch (op)
        {
-        case Expr_Op_Type_Add: 
+        case Expr_Op_Type_Add:
          x->value.i_value += y->value.i_value;
          break;
          x->value.i_value += y->value.i_value;
          break;
-        case Expr_Op_Type_Sub: 
+        case Expr_Op_Type_Sub:
          x->value.i_value -= y->value.i_value;
          break;
          x->value.i_value -= y->value.i_value;
          break;
-        case Expr_Op_Type_Mult: 
+        case Expr_Op_Type_Mult:
          x->value.i_value *= y->value.i_value;
          break;
          x->value.i_value *= y->value.i_value;
          break;
-        case Expr_Op_Type_Div: 
+        case Expr_Op_Type_Div:
          if (y->value.i_value == 0)
            error ("Illegal Expression:  Division by zero.");
          else
            x->value.i_value /= y->value.i_value;
          break;
          if (y->value.i_value == 0)
            error ("Illegal Expression:  Division by zero.");
          else
            x->value.i_value /= y->value.i_value;
          break;
-        case Expr_Op_Type_Mod: 
+        case Expr_Op_Type_Mod:
          x->value.i_value %= y->value.i_value;
          break;
          x->value.i_value %= y->value.i_value;
          break;
-        case Expr_Op_Type_Lshift: 
+        case Expr_Op_Type_Lshift:
          x->value.i_value <<= y->value.i_value;
          break;
          x->value.i_value <<= y->value.i_value;
          break;
-        case Expr_Op_Type_Rshift: 
+        case Expr_Op_Type_Rshift:
          x->value.i_value >>= y->value.i_value;
          break;
          x->value.i_value >>= y->value.i_value;
          break;
-        case Expr_Op_Type_BAND: 
+        case Expr_Op_Type_BAND:
          x->value.i_value &= y->value.i_value;
          break;
          x->value.i_value &= y->value.i_value;
          break;
-        case Expr_Op_Type_BOR: 
+        case Expr_Op_Type_BOR:
          x->value.i_value |= y->value.i_value;
          break;
          x->value.i_value |= y->value.i_value;
          break;
-        case Expr_Op_Type_BXOR: 
+        case Expr_Op_Type_BXOR:
          x->value.i_value ^= y->value.i_value;
          break;
          x->value.i_value ^= y->value.i_value;
          break;
-        case Expr_Op_Type_LAND: 
+        case Expr_Op_Type_LAND:
          x->value.i_value = x->value.i_value && y->value.i_value;
          break;
          x->value.i_value = x->value.i_value && y->value.i_value;
          break;
-        case Expr_Op_Type_LOR: 
+        case Expr_Op_Type_LOR:
          x->value.i_value = x->value.i_value || y->value.i_value;
          break;
 
        default:
          x->value.i_value = x->value.i_value || y->value.i_value;
          break;
 
        default:
-         error ("%s:%d: Internal compiler error\n", __FILE__, __LINE__); 
+         error ("%s:%d: Internal assembler error\n", __FILE__, __LINE__);
        }
       return x;
     }
        }
       return x;
     }
@@ -4354,20 +4625,20 @@ binary (Expr_Op_Type op, Expr_Node *x, Expr_Node *y)
 }
 
 static Expr_Node *
 }
 
 static Expr_Node *
-unary (Expr_Op_Type op, Expr_Node *x) 
+unary (Expr_Op_Type op, Expr_Node *x)
 {
   if (x->type == Expr_Node_Constant)
     {
       switch (op)
        {
 {
   if (x->type == Expr_Node_Constant)
     {
       switch (op)
        {
-       case Expr_Op_Type_NEG: 
+       case Expr_Op_Type_NEG:
          x->value.i_value = -x->value.i_value;
          break;
        case Expr_Op_Type_COMP:
          x->value.i_value = ~x->value.i_value;
          break;
        default:
          x->value.i_value = -x->value.i_value;
          break;
        case Expr_Op_Type_COMP:
          x->value.i_value = ~x->value.i_value;
          break;
        default:
-         error ("%s:%d: Internal compiler error\n", __FILE__, __LINE__); 
+         error ("%s:%d: Internal assembler error\n", __FILE__, __LINE__);
        }
       return x;
     }
        }
       return x;
     }
This page took 0.052125 seconds and 4 git commands to generate.