ChangeLog rotatation and copyright year update
[deliverable/binutils-gdb.git] / gas / config / tc-hppa.c
index 4b7c121b9d178a9fbb5dac1c122c7f72b7d184f3..57d7e96be72c87e462d6ee35b15f19be12b5f358 100644 (file)
@@ -1,6 +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 Free Software Foundation, Inc.
+   Copyright (C) 1989-2015 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -607,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
@@ -1264,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;
 
@@ -1301,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.  */
@@ -1401,7 +1395,8 @@ tc_gen_reloc (asection *section, fixS *fixp)
   /* ??? It might be better to hide this +8 stuff in tc_cfi_emit_pcrel_expr,
      undefine DIFF_EXPR_OK, and let these sorts of complex expressions fail
      when R_HPPA_COMPLEX == R_PARISC_UNIMPLEMENTED.  */
-  if (fixp->fx_r_type == R_HPPA_COMPLEX && fixp->fx_pcrel)
+  if (fixp->fx_r_type == (bfd_reloc_code_real_type) R_HPPA_COMPLEX
+      && fixp->fx_pcrel)
     {
       fixp->fx_r_type = R_HPPA_PCREL_CALL;
       fixp->fx_offset += 8;
@@ -2205,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)
            {
@@ -2517,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
@@ -2550,51 +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;
-      int retval;
+     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;
 
-      retval = 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
@@ -3203,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;
@@ -3263,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;
 
@@ -3757,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.  */
@@ -3825,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.  */
@@ -4050,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);
 
@@ -4129,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.  */
@@ -4218,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);
 
@@ -4276,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;
@@ -4340,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);
 
@@ -4398,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.  */
@@ -4407,6 +4429,7 @@ pa_ip (char *str)
                    flag = 0;
                    if (*s == ',')
                      {
+                       int uxor;
                        s++;
 
                        /* 64 bit conditions.  */
@@ -4420,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;
@@ -4430,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;
@@ -4463,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;
@@ -4487,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;
@@ -4499,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;
@@ -4509,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);
 
@@ -5260,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;
@@ -5269,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;
@@ -5279,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;
@@ -5288,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;
@@ -5298,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;
@@ -5310,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;
@@ -5319,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;
@@ -5450,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);
 
@@ -5969,6 +6002,10 @@ pa_build_unwind_subspace (struct call_info *call_info)
       != (SEC_ALLOC | SEC_LOAD | SEC_READONLY))
     return;
 
+  if (call_info->start_symbol == NULL)
+    /* This can happen if there were errors earlier on in the assembly.  */
+    return;
+
   /* Replace the start symbol with a local symbol that will be reduced
      to a section offset.  This avoids problems with weak functions with
      multiple definitions, etc.  */
@@ -6492,6 +6529,7 @@ process_exit (void)
   /* Mark the end of the function, stuff away the location of the frag
      for the end of the function, and finally call pa_build_unwind_subspace
      to add an entry in the unwind table.  */
+  (void) where;
   hppa_elf_mark_end_of_function ();
   pa_build_unwind_subspace (last_call_info);
 #else
@@ -6633,6 +6671,8 @@ pa_type_args (symbolS *symbolP, int is_export)
      to the SOM BFD backend.  */
 #ifdef obj_set_symbol_type
   obj_set_symbol_type (bfdsym, (int) type);
+#else
+  (void) type;
 #endif
 
   /* Now that the type of the exported symbol has been handled,
@@ -6655,6 +6695,8 @@ pa_type_args (symbolS *symbolP, int is_export)
          arg_reloc = pa_align_arg_reloc (temp, pa_build_arg_reloc (name));
 #if defined (OBJ_SOM) || defined (ELF_ARG_RELOC)
          symbol_arg_reloc_info (symbolP) |= arg_reloc;
+#else
+         (void) arg_reloc;
 #endif
          *input_line_pointer = c;
        }
@@ -6669,6 +6711,8 @@ pa_type_args (symbolS *symbolP, int is_export)
          arg_reloc = pa_build_arg_reloc (name);
 #if defined (OBJ_SOM) || defined (ELF_ARG_RELOC)
          symbol_arg_reloc_info (symbolP) |= arg_reloc;
+#else
+         (void) arg_reloc;
 #endif
          *input_line_pointer = c;
        }
This page took 0.03069 seconds and 4 git commands to generate.