2007-04-06 Matt Thomas <matt@netbsd.org>
authorMatt Thomas <matt@3am-software.com>
Fri, 6 Apr 2007 16:36:48 +0000 (16:36 +0000)
committerMatt Thomas <matt@3am-software.com>
Fri, 6 Apr 2007 16:36:48 +0000 (16:36 +0000)
* config/tc-vax.c (vax_cons): Added to support %pcrel{8,16,32}(exp)
to emit pcrel relocations by DWARF2 in non-code sections.  Borrowed
heavily from tc-sparc.c.  (vax_cons_fix_new): Likewise.

gas/ChangeLog
gas/config/tc-vax.c
gas/config/tc-vax.h

index 96abc6f..4c2e52c 100644 (file)
@@ -1,3 +1,9 @@
+2007-04-06  Matt Thomas  <matt@netbsd.org>
+
+       * config/tc-vax.c (vax_cons): Added to support %pcrel{8,16,32}(exp)
+       to emit pcrel relocations by DWARF2 in non-code sections.  Borrowed
+       heavily from tc-sparc.c.  (vax_cons_fix_new): Likewise.
+
 2007-04-04  Kazu Hirata  <kazu@codesourcery.com>
 
        * config/tc-m68k.c (HAVE_LONG_BRANCH): Add fido_a.
index 47b4fca..93cacd6 100644 (file)
@@ -3265,3 +3265,143 @@ md_begin (void)
       fP->high = &big_operand_bits[i][SIZE_OF_LARGE_NUMBER - 1];
     }
 }
+
+static char *vax_cons_special_reloc;
+
+void
+vax_cons (expressionS *exp, int size)
+{
+  char *save;
+
+  SKIP_WHITESPACE ();
+  vax_cons_special_reloc = NULL;
+  save = input_line_pointer;
+  if (input_line_pointer[0] == '%')
+    {
+      if (strncmp (input_line_pointer + 1, "pcrel", 5) == 0)
+       {
+         input_line_pointer += 6;
+         vax_cons_special_reloc = "pcrel";
+       }
+      if (vax_cons_special_reloc)
+       {
+         int bad = 0;
+
+         switch (size)
+           {
+           case 1:
+             if (*input_line_pointer != '8')
+               bad = 1;
+             input_line_pointer--;
+             break;
+           case 2:
+             if (input_line_pointer[0] != '1' || input_line_pointer[1] != '6')
+               bad = 1;
+             break;
+           case 4:
+             if (input_line_pointer[0] != '3' || input_line_pointer[1] != '2')
+               bad = 1;
+             break;
+           default:
+             bad = 1;
+             break;
+           }
+
+         if (bad)
+           {
+             as_bad (_("Illegal operands: Only %%r_%s%d allowed in %d-byte data fields"),
+                     vax_cons_special_reloc, size * 8, size);
+           }
+         else
+           {
+             input_line_pointer += 2;
+             if (*input_line_pointer != '(')
+               {
+                 as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+                         vax_cons_special_reloc, size * 8);
+                 bad = 1;
+               }
+           }
+
+         if (bad)
+           {
+             input_line_pointer = save;
+             vax_cons_special_reloc = NULL;
+           }
+         else
+           {
+             int c;
+             char *end = ++input_line_pointer;
+             int npar = 0;
+
+             while (! is_end_of_line[(c = *end)])
+               {
+                 if (c == '(')
+                   npar++;
+                 else if (c == ')')
+                   {
+                     if (!npar)
+                       break;
+                     npar--;
+                   }
+                 end++;
+               }
+
+             if (c != ')')
+               as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+                       vax_cons_special_reloc, size * 8);
+             else
+               {
+                 *end = '\0';
+                 expression (exp);
+                 *end = c;
+                 if (input_line_pointer != end)
+                   {
+                     as_bad (_("Illegal operands: %%r_%s%d requires arguments in ()"),
+                             vax_cons_special_reloc, size * 8);
+                   }
+                 else
+                   {
+                     input_line_pointer++;
+                     SKIP_WHITESPACE ();
+                     c = *input_line_pointer;
+                     if (! is_end_of_line[c] && c != ',')
+                       as_bad (_("Illegal operands: garbage after %%r_%s%d()"),
+                               vax_cons_special_reloc, size * 8);
+                   }
+               }
+           }
+       }
+    }
+  if (vax_cons_special_reloc == NULL)
+    expression (exp);
+}
+
+/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
+   reloc for a cons.  */
+
+void
+vax_cons_fix_new (fragS *frag, int where, unsigned int nbytes, expressionS *exp)
+{
+  bfd_reloc_code_real_type r;
+
+  r = (nbytes == 1 ? BFD_RELOC_8 :
+       (nbytes == 2 ? BFD_RELOC_16 : BFD_RELOC_32));
+
+  if (vax_cons_special_reloc)
+    {
+      if (*vax_cons_special_reloc == 'p')
+       {
+         switch (nbytes)
+           {
+           case 1: r = BFD_RELOC_8_PCREL; break;
+           case 2: r = BFD_RELOC_16_PCREL; break;
+           case 4: r = BFD_RELOC_32_PCREL; break;
+           default: abort ();
+           }
+       }
+    }
+
+  fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
+  vax_cons_special_reloc = NULL;
+}
index 715d54a..4f16e58 100644 (file)
 
 #define md_operand(x)
 
+#ifdef OBJ_ELF
+#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) vax_cons (EXP, NBYTES)
+#define TC_CONS_FIX_NEW vax_cons_fix_new
+void vax_cons (expressionS *, int);
+void vax_cons_fix_new (struct frag *, int, unsigned int, struct expressionS *);
+#endif
+
 extern const struct relax_type md_relax_table[];
 #define TC_GENERIC_RELAX_TABLE md_relax_table