ChangeLog rotatation and copyright year update
[deliverable/binutils-gdb.git] / gas / config / tc-hppa.c
index e55b2b45c145b6bc90d42ddb59090e06ca5a950a..57d7e96be72c87e462d6ee35b15f19be12b5f358 100644 (file)
@@ -1,7 +1,5 @@
 /* tc-hppa.c -- Assemble for the PA
-   Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 1989-2015 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -608,9 +606,6 @@ static int within_procedure;
    seen in each subspace.  */
 static label_symbol_struct *label_symbols_rootp = NULL;
 
-/* Holds the last field selector.  */
-static int hppa_field_selector;
-
 /* Nonzero when strict matching is enabled.  Zero otherwise.
 
    Each opcode in the table has a flag which indicates whether or
@@ -1265,7 +1260,8 @@ fix_new_hppa (fragS *frag,
    hppa_field_selector is set by the parse_cons_expression_hppa.  */
 
 void
-cons_fix_new_hppa (fragS *frag, int where, int size, expressionS *exp)
+cons_fix_new_hppa (fragS *frag, int where, int size, expressionS *exp,
+                  int hppa_field_selector)
 {
   unsigned int rel_type;
 
@@ -1302,9 +1298,6 @@ cons_fix_new_hppa (fragS *frag, int where, int size, expressionS *exp)
   fix_new_hppa (frag, where, size,
                (symbolS *) NULL, (offsetT) 0, exp, 0, rel_type,
                hppa_field_selector, size * 8, 0, 0);
-
-  /* Reset field selector to its default state.  */
-  hppa_field_selector = 0;
 }
 
 /* Mark (via expr_end) the end of an expression (I think).  FIXME.  */
@@ -2207,7 +2200,7 @@ pa_parse_number (char **s, int is_float)
                 register, so...  */
              have_prefix = TRUE;
            }
-         else if (S_GET_SEGMENT (sym) == &bfd_abs_section)
+         else if (S_GET_SEGMENT (sym) == bfd_abs_section_ptr)
            num = S_GET_VALUE (sym);
          else if (!strict)
            {
@@ -2519,11 +2512,12 @@ pa_chk_field_selector (char **str)
 /* Parse a .byte, .word, .long expression for the HPPA.  Called by
    cons via the TC_PARSE_CONS_EXPRESSION macro.  */
 
-void
+int
 parse_cons_expression_hppa (expressionS *exp)
 {
-  hppa_field_selector = pa_chk_field_selector (&input_line_pointer);
+  int hppa_field_selector = pa_chk_field_selector (&input_line_pointer);
   expression (exp);
+  return hppa_field_selector;
 }
 
 /* Evaluate an absolute expression EXP which may be modified by
@@ -2552,50 +2546,54 @@ pa_get_absolute_expression (struct pa_it *insn, char **strp)
   save_in = input_line_pointer;
   input_line_pointer = *strp;
   expression (&insn->exp);
-  /* This is not perfect, but is a huge improvement over doing nothing.
+  expr_end = input_line_pointer;
+  input_line_pointer = save_in;
+  if (insn->exp.X_op != O_constant)
+    {
+      /* We have a non-match in strict mode.  */
+      if (!strict)
+       as_bad (_("Bad segment (should be absolute)."));
+      return 0;
+    }
+  return evaluate_absolute (insn);
+}
 
-     The PA assembly syntax is ambiguous in a variety of ways.  Consider
+/* Get an absolute number.  The input string is terminated at the
+   first whitespace character.  */
+
+static int
+pa_get_number (struct pa_it *insn, char **strp)
+{
+  char *save_in;
+  char *s, c;
+  int result;
+
+  save_in = input_line_pointer;
+  input_line_pointer = *strp;
+
+  /* The PA assembly syntax is ambiguous in a variety of ways.  Consider
      this string "4 %r5"  Is that the number 4 followed by the register
-     r5, or is that 4 MOD r5?
+     r5, or is that 4 MOD r5?  This situation occurs for example in the
+     coprocessor load and store instructions.  Previously, calling
+     pa_get_absolute_expression directly results in r5 being entered
+     in the symbol table.
 
-     If we get a modulo expression when looking for an absolute, we try
-     again cutting off the input string at the first whitespace character.  */
-  if (insn->exp.X_op == O_modulus)
-    {
-      char *s, c;
+     So, when looking for an absolute number, we cut off the input string
+     at the first whitespace character.  Thus, expressions should generally
+     contain no whitespace.  */
 
-      input_line_pointer = *strp;
-      s = *strp;
-      while (*s != ',' && *s != ' ' && *s != '\t')
-       s++;
+  s = *strp;
+  while (*s != ',' && *s != ' ' && *s != '\t')
+    s++;
 
-      c = *s;
-      *s = 0;
+  c = *s;
+  *s = 0;
 
-      pa_get_absolute_expression (insn, strp);
+  result = pa_get_absolute_expression (insn, strp);
 
-      input_line_pointer = save_in;
-      *s = c;
-      return evaluate_absolute (insn);
-    }
-  /* When in strict mode we have a non-match, fix up the pointers
-     and return to our caller.  */
-  if (insn->exp.X_op != O_constant && strict)
-    {
-      expr_end = input_line_pointer;
-      input_line_pointer = save_in;
-      return 0;
-    }
-  if (insn->exp.X_op != O_constant)
-    {
-      as_bad (_("Bad segment (should be absolute)."));
-      expr_end = input_line_pointer;
-      input_line_pointer = save_in;
-      return 0;
-    }
-  expr_end = input_line_pointer;
   input_line_pointer = save_in;
-  return evaluate_absolute (insn);
+  *s = c;
+  return result;
 }
 
 /* Given an argument location specification return the associated
@@ -3204,7 +3202,7 @@ pa_ip (char *str)
   const char *args;
   int match = FALSE;
   int comma = 0;
-  int cmpltr, nullif, flag, cond, num;
+  int cmpltr, nullif, flag, cond, need_cond, num;
   int immediate_check = 0, pos = -1, len = -1;
   unsigned long opcode;
   struct pa_opcode *insn;
@@ -3264,6 +3262,7 @@ pa_ip (char *str)
       opcode = insn->match;
       strict = (insn->flags & FLAG_STRICT);
       memset (&the_insn, 0, sizeof (the_insn));
+      need_cond = 1;
 
       the_insn.reloc = R_HPPA_NONE;
 
@@ -3758,6 +3757,8 @@ pa_ip (char *str)
                  else
                    break;
 
+                 /* Condition is not required with "dc".  */
+                 need_cond = 0;
                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
 
                /* Handle 32 bit carry for ADD.  */
@@ -3826,6 +3827,8 @@ pa_ip (char *str)
                  else
                    break;
 
+                 /* Condition is not required with "db".  */
+                 need_cond = 0;
                  INSERT_FIELD_AND_CONTINUE (opcode, flag, 11);
 
                /* Handle 32 bit borrow for SUB.  */
@@ -3969,12 +3972,6 @@ pa_ip (char *str)
 
                  /* Handle an add condition.  */
                  case 'A':
-                   /* PR gas/11395
-                      If we are looking for 64-bit add conditions and we
-                      do not have the ",*" prefix, then we have no match.  */
-                   if (*s != ',')
-                     break;
-                   /* Fall through.  */
                  case 'a':
                    cmpltr = 0;
                    flag = 0;
@@ -4057,6 +4054,11 @@ pa_ip (char *str)
                          as_bad (_("Invalid Add Condition: %s"), name);
                        *s = c;
                      }
+                   /* Except with "dc", we have a match failure with
+                      'A' if we don't have a doubleword condition.  */
+                   else if (*args == 'A' && need_cond)
+                     break;
+
                    opcode |= cmpltr << 13;
                    INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
 
@@ -4136,8 +4138,11 @@ pa_ip (char *str)
                            s += 2;
                          }
                        else
-                         as_bad (_("Invalid Bit Branch Condition: %c"), *s);
+                         as_bad (_("Invalid Branch On Bit Condition: %c"), *s);
                      }
+                   else
+                     as_bad (_("Missing Branch On Bit Condition"));
+
                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 15);
 
                  /* Handle a compare/subtract condition.  */
@@ -4225,6 +4230,11 @@ pa_ip (char *str)
                                  name);
                        *s = c;
                      }
+                   /* Except with "db", we have a match failure with
+                      'S' if we don't have a doubleword condition.  */
+                   else if (*args == 'S' && need_cond)
+                     break;
+
                    opcode |= cmpltr << 13;
                    INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
 
@@ -4283,7 +4293,7 @@ pa_ip (char *str)
 
                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
 
-                   /* Handle a logical instruction condition.  */
+                 /* Handle a logical instruction condition.  */
                  case 'L':
                  case 'l':
                    cmpltr = 0;
@@ -4347,6 +4357,10 @@ pa_ip (char *str)
                          as_bad (_("Invalid Logical Instruction Condition."));
                        *s = c;
                      }
+                   /* 32-bit is default for no condition.  */
+                   else if (*args == 'L')
+                     break;
+
                    opcode |= cmpltr << 13;
                    INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
 
@@ -4405,6 +4419,7 @@ pa_ip (char *str)
                          as_bad (_("Invalid Shift/Extract/Deposit Condition."));
                        *s = c;
                      }
+
                    INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13);
 
                  /* Handle a unit instruction condition.  */
@@ -4414,6 +4429,7 @@ pa_ip (char *str)
                    flag = 0;
                    if (*s == ',')
                      {
+                       int uxor;
                        s++;
 
                        /* 64 bit conditions.  */
@@ -4427,6 +4443,9 @@ pa_ip (char *str)
                        else if (*s == '*')
                          break;
 
+                       /* The uxor instruction only supports unit conditions
+                          not involving carries.  */
+                       uxor = (opcode & 0xfc000fc0) == 0x08000380;
                        if (strncasecmp (s, "sbz", 3) == 0)
                          {
                            cmpltr = 2;
@@ -4437,17 +4456,17 @@ pa_ip (char *str)
                            cmpltr = 3;
                            s += 3;
                          }
-                       else if (strncasecmp (s, "sdc", 3) == 0)
+                       else if (!uxor && strncasecmp (s, "sdc", 3) == 0)
                          {
                            cmpltr = 4;
                            s += 3;
                          }
-                       else if (strncasecmp (s, "sbc", 3) == 0)
+                       else if (!uxor && strncasecmp (s, "sbc", 3) == 0)
                          {
                            cmpltr = 6;
                            s += 3;
                          }
-                       else if (strncasecmp (s, "shc", 3) == 0)
+                       else if (!uxor && strncasecmp (s, "shc", 3) == 0)
                          {
                            cmpltr = 7;
                            s += 3;
@@ -4470,19 +4489,19 @@ pa_ip (char *str)
                            flag = 1;
                            s += 3;
                          }
-                       else if (strncasecmp (s, "ndc", 3) == 0)
+                       else if (!uxor && strncasecmp (s, "ndc", 3) == 0)
                          {
                            cmpltr = 4;
                            flag = 1;
                            s += 3;
                          }
-                       else if (strncasecmp (s, "nbc", 3) == 0)
+                       else if (!uxor && strncasecmp (s, "nbc", 3) == 0)
                          {
                            cmpltr = 6;
                            flag = 1;
                            s += 3;
                          }
-                       else if (strncasecmp (s, "nhc", 3) == 0)
+                       else if (!uxor && strncasecmp (s, "nhc", 3) == 0)
                          {
                            cmpltr = 7;
                            flag = 1;
@@ -4494,7 +4513,7 @@ pa_ip (char *str)
                            flag = 0;
                            s += 3;
                          }
-                       else if (strncasecmp (s, "swc", 3) == 0)
+                       else if (!uxor && strncasecmp (s, "swc", 3) == 0)
                          {
                            cmpltr = 5;
                            flag = 0;
@@ -4506,7 +4525,7 @@ pa_ip (char *str)
                            flag = 1;
                            s += 3;
                          }
-                       else if (strncasecmp (s, "nwc", 3) == 0)
+                       else if (!uxor && strncasecmp (s, "nwc", 3) == 0)
                          {
                            cmpltr = 5;
                            flag = 1;
@@ -4516,6 +4535,10 @@ pa_ip (char *str)
                        else if (*args != 'U' || (*s != ' ' && *s != '\t'))
                          as_bad (_("Invalid Unit Instruction Condition."));
                      }
+                   /* 32-bit is default for no condition.  */
+                   else if (*args == 'U')
+                     break;
+
                    opcode |= cmpltr << 13;
                    INSERT_FIELD_AND_CONTINUE (opcode, flag, 12);
 
@@ -5267,7 +5290,7 @@ pa_ip (char *str)
            case 'v':
              if (*s++ != ',')
                as_bad (_("Invalid SFU identifier"));
-             num = pa_get_absolute_expression (&the_insn, &s);
+             num = pa_get_number (&the_insn, &s);
              if (strict && the_insn.exp.X_op != O_constant)
                break;
              s = expr_end;
@@ -5276,7 +5299,7 @@ pa_ip (char *str)
 
            /* Handle a 20 bit SOP field for spop0.  */
            case 'O':
-             num = pa_get_absolute_expression (&the_insn, &s);
+             num = pa_get_number (&the_insn, &s);
              if (strict && the_insn.exp.X_op != O_constant)
                break;
              s = expr_end;
@@ -5286,7 +5309,7 @@ pa_ip (char *str)
 
            /* Handle a 15bit SOP field for spop1.  */
            case 'o':
-             num = pa_get_absolute_expression (&the_insn, &s);
+             num = pa_get_number (&the_insn, &s);
              if (strict && the_insn.exp.X_op != O_constant)
                break;
              s = expr_end;
@@ -5295,7 +5318,7 @@ pa_ip (char *str)
 
            /* Handle a 10bit SOP field for spop3.  */
            case '0':
-             num = pa_get_absolute_expression (&the_insn, &s);
+             num = pa_get_number (&the_insn, &s);
              if (strict && the_insn.exp.X_op != O_constant)
                break;
              s = expr_end;
@@ -5305,7 +5328,7 @@ pa_ip (char *str)
 
            /* Handle a 15 bit SOP field for spop2.  */
            case '1':
-             num = pa_get_absolute_expression (&the_insn, &s);
+             num = pa_get_number (&the_insn, &s);
              if (strict && the_insn.exp.X_op != O_constant)
                break;
              s = expr_end;
@@ -5317,7 +5340,7 @@ pa_ip (char *str)
            case 'u':
              if (*s++ != ',')
                as_bad (_("Invalid COPR identifier"));
-             num = pa_get_absolute_expression (&the_insn, &s);
+             num = pa_get_number (&the_insn, &s);
              if (strict && the_insn.exp.X_op != O_constant)
                break;
              s = expr_end;
@@ -5326,7 +5349,7 @@ pa_ip (char *str)
 
            /* Handle a 22bit SOP field for copr.  */
            case '2':
-             num = pa_get_absolute_expression (&the_insn, &s);
+             num = pa_get_number (&the_insn, &s);
              if (strict && the_insn.exp.X_op != O_constant)
                break;
              s = expr_end;
@@ -5457,7 +5480,10 @@ pa_ip (char *str)
                case 't':
                  if (!pa_parse_number (&s, 3))
                    break;
-                 num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE;
+                 /* RSEL should not be set.  */
+                 if (pa_number & FP_REG_RSEL)
+                   break;
+                 num = pa_number - FP_REG_BASE;
                  CHECK_FIELD (num, 31, 0, 0);
                  INSERT_FIELD_AND_CONTINUE (opcode, num, 0);
 
This page took 0.033402 seconds and 4 git commands to generate.