gas/
[deliverable/binutils-gdb.git] / gas / config / tc-vax.c
index 299746b802d85a7946a8071349d8180b4bc3c331..b8cdec971482016486212a7a0029d59c03747d20 100644 (file)
@@ -1,13 +1,13 @@
 /* tc-vax.c - vax-specific -
    Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1998, 2000, 2001, 2002,
-   2003, 2004, 2005
+   2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
@@ -291,9 +291,12 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
     fixP->fx_done = 1;
 }
 
-long
-md_chars_to_number (unsigned char con[],       /* Low order byte 1st.  */
-                   int nbytes)         /* Number of bytes in the input.  */
+/* Convert a number from VAX byte order (little endian)
+   into host byte order.
+   con         is the buffer to convert,
+   nbytes      is the length of the given buffer.  */
+static long
+md_chars_to_number (unsigned char con[], int nbytes)
 {
   long retval;
 
@@ -803,13 +806,11 @@ static const short int vax_operand_width_size[256] =
    cases, we do the same idea. JACBxxx are all marked with a 'b!'
    JAOBxxx & JSOBxxx are marked with a 'b:'.  */
 #if (VIT_OPCODE_SYNTHETIC != 0x80000000)
-You have just broken the encoding below, which assumes the sign bit
-  means 'I am an imaginary instruction'.
+#error "You have just broken the encoding below, which assumes the sign bit means 'I am an imaginary instruction'."
 #endif
 
 #if (VIT_OPCODE_SPECIAL != 0x40000000)
-  You have just broken the encoding below, which assumes the 0x40 M bit means
-  'I am not to be "optimised" the way normal branches are'.
+#error "You have just broken the encoding below, which assumes the 0x40 M bit means 'I am not to be "optimised" the way normal branches are'."
 #endif
 
 static const struct vot
@@ -958,11 +959,11 @@ vip_begin (int synthetic_too,             /* 1 means include jXXX op-codes.  */
   op_hash = hash_new ();
 
   for (vP = votstrs; *vP->vot_name && !retval; vP++)
-    retval = hash_insert (op_hash, vP->vot_name, (PTR) &vP->vot_detail);
+    retval = hash_insert (op_hash, vP->vot_name, (void *) &vP->vot_detail);
 
   if (synthetic_too)
     for (vP = synthetic_votstrs; *vP->vot_name && !retval; vP++)
-      retval = hash_insert (op_hash, vP->vot_name, (PTR) &vP->vot_detail);
+      retval = hash_insert (op_hash, vP->vot_name, (void *) &vP->vot_detail);
 
 #ifndef CONST_TABLE
   vip_op_defaults (immediate, indirect, displen);
@@ -998,18 +999,18 @@ vip_begin (int synthetic_too,             /* 1 means include jXXX op-codes.  */
        R14     SP
        R15     PC  */
 
-#define AP (12)
-#define FP (13)
-#define SP (14)
-#define PC (15)
+#define AP 12
+#define FP 13
+#define SP 14
+#define PC 15
 
-static int                             /* Return -1 or 0:15.  */
-vax_reg_parse (char c1, char c2,       /* 3 chars of register name.  */
-              char c3, char c4)        /* c3 == 0 if 2-character reg name.  */
+/* Returns the register number of something like '%r15' or 'ap', supplied
+   in four single chars. Returns -1 if the register isn't recognized,
+   0..15 otherwise.  */
+static int
+vax_reg_parse (char c1, char c2, char c3, char c4)
 {
-  int retval;
-
-  retval = -1;
+  int retval = -1;
 
 #ifdef OBJ_ELF
   if (c1 != '%')       /* Register prefixes are mandatory for ELF.  */
@@ -1229,12 +1230,12 @@ vax_reg_parse (char c1, char c2,        /* 3 chars of register name.  */
   {@}#foo, no S^               8+@     PC      " i"    optional
   {@}{q^}{(Rn)}                10+@+q  option  " bwl"  optional  */
 
+/* Dissect user-input 'optext' (which is something like "@B^foo@bar(AP)[FP]:")
+   using the vop in vopP. vopP's vop_access and vop_width. We fill _ndx, _reg,
+   _mode, _short, _warn, _error, _expr_begin, _expr_end and _nbytes.  */
+
 static void
-vip_op (char *optext, /* user's input string e.g.: "@B^foo@bar(AP)[FP]:" */
-       struct vop *vopP) /* Input fields: vop_access, vop_width.
-                            Output fields: _ndx, _reg, _mode, _short, _warn,
-                            _error _expr_begin, _expr_end, _nbytes.
-                            vop_nbytes : number of bytes in a datum.  */
+vip_op (char *optext, struct vop *vopP)
 {
   /* Track operand text forward.  */
   char *p;
@@ -2034,8 +2035,6 @@ main (void)
    We declare arrays non-local in case some of our tiny-minded machines
    default to small stacks. Also, helps with some debuggers.  */
 
-#include <stdio.h>
-
 char answer[100];              /* Human types into here.  */
 char *p;                       /*  */
 char *myerr;
@@ -2142,9 +2141,8 @@ main (void)
     }
 }
 
-mumble (text, value)
-     char *text;
-     int value;
+void
+mumble (char *text, int value)
 {
   printf ("%s:", text);
   if (value >= 0)
@@ -2204,9 +2202,9 @@ struct option md_longopts[] =
 {
 #ifdef OBJ_ELF
 #define OPTION_PIC (OPTION_MD_BASE)
-  {"pic", no_argument, NULL, OPTION_PIC},
+  { "pic", no_argument, NULL, OPTION_PIC },
 #endif
-  {NULL, no_argument, NULL, 0}
+  { NULL, no_argument, NULL, 0 }
 };
 size_t md_longopts_size = sizeof (md_longopts);
 
@@ -2408,6 +2406,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
   return reloc;
 }
 
+/* vax:md_assemble() emit frags for 1 instruction given in textual form.  */
 void
 md_assemble (char *instruction_string)
 {
@@ -3266,3 +3265,149 @@ 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;
+}
+
+char *
+md_atof (int type, char * litP, int * sizeP)
+{
+  return vax_md_atof (type, litP, sizeP);
+}
This page took 0.027362 seconds and 4 git commands to generate.