gas TC_PARSE_CONS_EXPRESSION communication with TC_CONS_FIX_NEW
[deliverable/binutils-gdb.git] / gas / config / tc-rx.c
index 4fa0f6737a5cf905e7c899d7829544cb7bd3e014..c4842f9aecf6f5d859f461e1739770b72996de08 100644 (file)
@@ -1,6 +1,5 @@
 /* tc-rx.c -- Assembler for the Renesas RX
-   Copyright 2008, 2009, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 2008-2014 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -46,7 +45,7 @@ const char EXP_CHARS[]            = "eE";
 const char FLT_CHARS[]            = "dD";
 \f
 /* ELF flags to set in the output file header.  */
-static int elf_flags = 0;
+static int elf_flags = E_FLAG_RX_ABI;
 
 bfd_boolean rx_use_conventional_section_names = FALSE;
 static bfd_boolean rx_use_small_data_limit = FALSE;
@@ -56,6 +55,10 @@ static int rx_num_int_regs = 0;
 int rx_pid_register;
 int rx_gp_register;
 
+enum rx_cpu_types rx_cpu = RX600;
+
+static void rx_fetchalign (int ignore ATTRIBUTE_UNUSED);
+
 enum options
 {
   OPTION_BIG = OPTION_MD_BASE,
@@ -68,6 +71,9 @@ enum options
   OPTION_RELAX,
   OPTION_PID,
   OPTION_INT_REGS,
+  OPTION_USES_GCC_ABI,
+  OPTION_USES_RX_ABI,
+  OPTION_CPU,
 };
 
 #define RX_SHORTOPTS ""
@@ -92,6 +98,9 @@ struct option md_longopts[] =
   {"relax", no_argument, NULL, OPTION_RELAX},
   {"mpid", no_argument, NULL, OPTION_PID},
   {"mint-register", required_argument, NULL, OPTION_INT_REGS},
+  {"mgcc-abi", no_argument, NULL, OPTION_USES_GCC_ABI},
+  {"mrx-abi", no_argument, NULL, OPTION_USES_RX_ABI},
+  {"mcpu",required_argument,NULL,OPTION_CPU},
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof (md_longopts);
@@ -141,6 +150,30 @@ md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
     case OPTION_INT_REGS:
       rx_num_int_regs = atoi (optarg);
       return 1;
+
+    case OPTION_USES_GCC_ABI:
+      elf_flags &= ~ E_FLAG_RX_ABI;
+      return 1;
+
+    case OPTION_USES_RX_ABI:
+      elf_flags |= E_FLAG_RX_ABI;
+      return 1;
+
+    case OPTION_CPU:
+      if (strcasecmp (arg, "rx100") == 0)
+        rx_cpu = RX100;
+      else if (strcasecmp (arg, "rx200") == 0)
+       rx_cpu = RX200;
+      else if (strcasecmp (arg, "rx600") == 0)
+       rx_cpu = RX600;
+      else if (strcasecmp (arg, "rx610") == 0)
+       rx_cpu = RX610;
+      else
+       {
+         as_warn (_("unrecognised RX CPU type %s"), arg);
+         break;
+       }
+      return 1;
     }
   return 0;
 }
@@ -159,6 +192,7 @@ md_show_usage (FILE * stream)
   fprintf (stream, _("  --mrelax\n"));
   fprintf (stream, _("  --mpid\n"));
   fprintf (stream, _("  --mint-register=<value>\n"));
+  fprintf (stream, _("  --mcpu=<rx100|rx200|rx600|rx610>\n"));
 }
 
 static void
@@ -210,7 +244,7 @@ rx_include (int ignore)
   char * path;
   char * filename;
   char * current_filename;
-  char * eof;
+  char * last_char;
   char * p;
   char * d;
   char * f;
@@ -229,17 +263,17 @@ rx_include (int ignore)
 
   /* Get the filename.  Spaces are allowed, NUL characters are not.  */
   filename = input_line_pointer;
-  eof = find_end_of_line (filename, FALSE);
-  input_line_pointer = eof;
-
-  while (eof >= filename && (* eof == ' ' || * eof == '\n'))
-    -- eof;
-  end_char = *(++ eof);
-  * eof = 0;
-  if (eof == filename)
+  last_char = find_end_of_line (filename, FALSE);
+  input_line_pointer = last_char;
+
+  while (last_char >= filename && (* last_char == ' ' || * last_char == '\n'))
+    -- last_char;
+  end_char = *(++ last_char);
+  * last_char = 0;
+  if (last_char == filename)
     {
       as_bad (_("no filename following .INCLUDE pseudo-op"));
-      * eof = end_char;
+      * last_char = end_char;
       return;
     }
 
@@ -351,7 +385,7 @@ rx_include (int ignore)
       input_scrub_insert_file (path);
     }
 
-  * eof = end_char;
+  * last_char = end_char;
 }
 
 static void
@@ -600,6 +634,8 @@ const pseudo_typeS md_pseudo_table[] =
   { "int",     cons,           4 },
   { "word",    cons,           4 },
 
+  { "fetchalign", rx_fetchalign, 0 },
+
   /* End of list marker.  */
   { NULL,      NULL,           0 }
 };
@@ -648,9 +684,14 @@ md_begin (void)
 char * rx_lex_start;
 char * rx_lex_end;
 
+/* These negative numbers are found in rx_bytesT.n_base for non-opcode
+   md_frags */
+#define RX_NBASE_FETCHALIGN    -1
+
 typedef struct rx_bytesT
 {
   char base[4];
+  /* If this is negative, it's a special-purpose frag as per the defines above. */
   int n_base;
   char ops[8];
   int n_ops;
@@ -678,6 +719,31 @@ typedef struct rx_bytesT
 } rx_bytesT;
 
 static rx_bytesT rx_bytes;
+/* We set n_ops to be "size of next opcode" if the next opcode doesn't relax.  */
+static rx_bytesT *fetchalign_bytes = NULL;
+
+static void
+rx_fetchalign (int ignore ATTRIBUTE_UNUSED)
+{
+  char * bytes;
+  fragS * frag_then;
+
+  memset (& rx_bytes, 0, sizeof (rx_bytes));
+  rx_bytes.n_base = RX_NBASE_FETCHALIGN;
+
+  bytes = frag_more (8);
+  frag_then = frag_now;
+  frag_variant (rs_machine_dependent,
+               0 /* max_chars */,
+               0 /* var */,
+               0 /* subtype */,
+               0 /* symbol */,
+               0 /* offset */,
+               0 /* opcode */);
+  frag_then->fr_opcode = bytes;
+  frag_then->fr_subtype = 0;
+  fetchalign_bytes = frag_then->tc_frag_data;
+}
 
 void
 rx_relax (int type, int pos)
@@ -933,7 +999,7 @@ rx_wrap (void)
 void
 rx_frag_init (fragS * fragP)
 {
-  if (rx_bytes.n_relax || rx_bytes.link_relax)
+  if (rx_bytes.n_relax || rx_bytes.link_relax || rx_bytes.n_base < 0)
     {
       fragP->tc_frag_data = malloc (sizeof (rx_bytesT));
       memcpy (fragP->tc_frag_data, & rx_bytes, sizeof (rx_bytesT));
@@ -1049,8 +1115,12 @@ md_assemble (char * str)
     {
       bytes = frag_more (rx_bytes.n_base + rx_bytes.n_ops);
       frag_then = frag_now;
+      if (fetchalign_bytes)
+       fetchalign_bytes->n_ops = rx_bytes.n_base + rx_bytes.n_ops;
     }
 
+  fetchalign_bytes = NULL;
+
   APPEND (base, n_base);
   APPEND (ops, n_ops);
 
@@ -1413,6 +1483,18 @@ md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTR
   return delta;
 }
 
+/* Given a frag FRAGP, return the "next" frag that contains an
+   opcode.  Assumes the next opcode is relaxable, and thus rs_machine_dependent.  */
+
+static fragS *
+rx_next_opcode (fragS *fragP)
+{
+  do {
+    fragP = fragP->fr_next;
+  } while (fragP && fragP->fr_type != rs_machine_dependent);
+  return fragP;
+}
+
 /* Given the new addresses for this relax pass, figure out how big
    each opcode must be.  We store the total number of bytes needed in
    fr_subtype.  The return value is the difference between the size
@@ -1437,6 +1519,34 @@ rx_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
           (long) fragP->fr_fix, (long) fragP->fr_var, (long) fragP->fr_offset,
           fragP->fr_literal, fragP->fr_opcode, fragP->fr_type, fragP->fr_subtype, stretch);
 
+  mypc = fragP->fr_address + (fragP->fr_opcode - fragP->fr_literal);
+
+  if (fragP->tc_frag_data->n_base == RX_NBASE_FETCHALIGN)
+    {
+      unsigned int next_size;
+      if (fragP->fr_next == NULL)
+       return 0;
+
+      next_size = fragP->tc_frag_data->n_ops;
+      if (next_size == 0)
+       {
+         fragS *n = rx_next_opcode (fragP);
+         next_size = n->fr_subtype;
+       }
+
+      fragP->fr_subtype = (8-(mypc & 7)) & 7;
+      tprintf("subtype %u\n", fragP->fr_subtype);
+      if (fragP->fr_subtype >= next_size)
+       fragP->fr_subtype = 0;
+      tprintf ("\033[34m -> mypc %lu next_size %u new %d old %d delta %d (fetchalign)\033[0m\n",
+              mypc & 7,
+              next_size, fragP->fr_subtype, oldsize, fragP->fr_subtype-oldsize);
+
+      newsize = fragP->fr_subtype;
+
+      return newsize - oldsize;
+    }
+
   optype = rx_opcode_type (fragP->fr_opcode);
 
   /* In the one case where we have both a disp and imm relaxation, we want
@@ -1485,7 +1595,6 @@ rx_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
       return newsize - oldsize;
     }
 
-  mypc = fragP->fr_address + (fragP->fr_opcode - fragP->fr_literal);
   if (sym_addr > mypc)
     addr0 += stretch;
 
@@ -1644,13 +1753,29 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
   {
     int i;
 
-    printf ("lit %08x opc %08x", (int) fragP->fr_literal, (int) fragP->fr_opcode);
+    printf ("lit 0x%p opc 0x%p", fragP->fr_literal, fragP->fr_opcode);
     for (i = 0; i < 10; i++)
       printf (" %02x", (unsigned char) (fragP->fr_opcode[i]));
     printf ("\n");
   }
 #endif
 
+  if (fragP->tc_frag_data->n_base == RX_NBASE_FETCHALIGN)
+    {
+      int count = fragP->fr_subtype;
+      if (count == 0)
+       ;
+      else if (count > BIGGEST_NOP)
+       {
+         op[0] = 0x2e;
+         op[1] = count;
+       }
+      else if (count > 0)
+       {
+         memcpy (op, nops[count], count);
+       }
+    }
+
   /* In the one case where we have both a disp and imm relaxation, we want
      the imm relaxation here.  */
   ri = 0;
@@ -2045,10 +2170,9 @@ void
 rx_cons_fix_new (fragS *       frag,
                 int            where,
                 int            size,
-                expressionS *  exp)
+                expressionS *  exp,
+                bfd_reloc_code_real_type type)
 {
-  bfd_reloc_code_real_type type;
-
   switch (size)
     {
     case 1:
This page took 0.027788 seconds and 4 git commands to generate.