Remove redundant returns in void functions.
[deliverable/binutils-gdb.git] / gas / config / tc-m32r.c
index 062181e05ed75b98cff7c6b42b0f60f3201c0542..58f90541d28fe9f3e88358ca35ff4eab996c489c 100644 (file)
@@ -1,5 +1,5 @@
-/* tc-m32r.c -- Assembler for the Mitsubishi M32R.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000
+/* tc-m32r.c -- Assembler for the Renesas M32R.
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
    Boston, MA 02111-1307, USA.  */
 
 #include <stdio.h>
-#include <ctype.h>
 #include "as.h"
+#include "safe-ctype.h"
 #include "subsegs.h"
 #include "symcat.h"
 #include "opcodes/m32r-desc.h"
 #include "opcodes/m32r-opc.h"
 #include "cgen.h"
+#include "elf/m32r.h"
 
 /* Linked list of symbols that are debugging symbols to be defined as the
    beginning of the current instruction.  */
@@ -93,21 +94,41 @@ static const char *m32r_cpu_desc;
    shouldn't assume or require it to).  */
 static int warn_unmatched_high = 0;
 
-/* Non-zero if -m32rx has been specified, in which case support for the
-   extended M32RX instruction set should be enabled.  */
-static int enable_m32rx = 0;
+/* 1 if -m32rx has been specified, in which case support for
+     the extended M32RX instruction set should be enabled.
+   2 if -m32r2 has been specified, in which case support for
+     the extended M32R2 instruction set should be enabled.  */
+static int enable_m32rx = 0; /* Default to M32R.  */
 
 /* Non-zero if -m32rx -hidden has been specified, in which case support for
    the special M32RX instruction set should be enabled.  */
 static int enable_special = 0;
 
+/* Non-zero if -bitinst has been specified, in which case support
+   for extended M32R bit-field instruction set should be enabled.  */
+static int enable_special_m32r = 0;
+
+/* Non-zero if -float has been specified, in which case support for
+   extended M32R floating point instruction set should be enabled.  */
+static int enable_special_float = 0;
+
 /* Non-zero if the programmer should be warned when an explicit parallel
    instruction might have constraint violations.  */
 static int warn_explicit_parallel_conflicts = 1;
 
+/* Non-zero if the programmer should receive an error message when an
+   explicit parallel instruction might have constraint violations.  */
+static int error_explicit_parallel_conflicts = 1;
+
 /* Non-zero if insns can be made parallel.  */
+static int use_parallel = 1;
+
+/* Non-zero if optimizations should be performed.  */
 static int optimize;
 
+/* m32r er_flags.  */
+static int m32r_flags = 0;
+
 /* Stuff for .scomm symbols.  */
 static segT     sbss_section;
 static asection scom_section;
@@ -115,7 +136,7 @@ static asymbol  scom_symbol;
 
 const char comment_chars[]        = ";";
 const char line_comment_chars[]   = "#";
-const char line_separator_chars[] = "";
+const char line_separator_chars[] = "!";
 const char EXP_CHARS[]            = "eE";
 const char FLT_CHARS[]            = "dD";
 
@@ -146,15 +167,28 @@ struct m32r_hi_fixup
 
 static struct m32r_hi_fixup *m32r_hi_fixup_list;
 \f
+struct {
+  enum bfd_architecture bfd_mach;
+  int mach_flags;
+} mach_table[] =
+{
+  { bfd_mach_m32r,  (1<<MACH_M32R) },
+  { bfd_mach_m32rx, (1<<MACH_M32RX) },
+  { bfd_mach_m32r2, (1<<MACH_M32R2) }
+};
+
+static void allow_m32rx (int);
+
 static void
-allow_m32rx (on)
-     int on;
+allow_m32rx (int on)
 {
   enable_m32rx = on;
 
   if (stdoutput != NULL)
-    bfd_set_arch_mach (stdoutput, TARGET_ARCH,
-                      enable_m32rx ? bfd_mach_m32rx : bfd_mach_m32r);
+    bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach_table[on].bfd_mach);
+
+  if (gas_cgen_cpu_desc != NULL)
+    gas_cgen_cpu_desc->machs = mach_table[on].mach_flags;
 }
 \f
 #define M32R_SHORTOPTS "O"
@@ -163,20 +197,42 @@ const char *md_shortopts = M32R_SHORTOPTS;
 
 struct option md_longopts[] =
 {
-#define OPTION_M32R            (OPTION_MD_BASE)
-#define OPTION_M32RX           (OPTION_M32R + 1)
-#define OPTION_WARN_PARALLEL   (OPTION_M32RX + 1)
-#define OPTION_NO_WARN_PARALLEL        (OPTION_WARN_PARALLEL + 1)
-#define OPTION_SPECIAL         (OPTION_NO_WARN_PARALLEL + 1)
-#define OPTION_WARN_UNMATCHED  (OPTION_SPECIAL + 1)
+#define OPTION_M32R             (OPTION_MD_BASE)
+#define OPTION_M32RX            (OPTION_M32R + 1)
+#define OPTION_M32R2            (OPTION_M32RX + 1)
+#define OPTION_BIG               (OPTION_M32R2 + 1)
+#define OPTION_LITTLE            (OPTION_BIG + 1)
+#define OPTION_PARALLEL          (OPTION_LITTLE + 1)
+#define OPTION_NO_PARALLEL       (OPTION_PARALLEL + 1)
+#define OPTION_WARN_PARALLEL    (OPTION_NO_PARALLEL + 1)
+#define OPTION_NO_WARN_PARALLEL         (OPTION_WARN_PARALLEL + 1)
+#define OPTION_ERROR_PARALLEL    (OPTION_NO_WARN_PARALLEL + 1)
+#define OPTION_NO_ERROR_PARALLEL (OPTION_ERROR_PARALLEL + 1)
+#define OPTION_SPECIAL          (OPTION_NO_ERROR_PARALLEL + 1)
+#define OPTION_SPECIAL_M32R      (OPTION_SPECIAL + 1)
+#define OPTION_SPECIAL_FLOAT     (OPTION_SPECIAL_M32R + 1)
+#define OPTION_WARN_UNMATCHED   (OPTION_SPECIAL_FLOAT + 1)
 #define OPTION_NO_WARN_UNMATCHED (OPTION_WARN_UNMATCHED + 1)
   {"m32r",  no_argument, NULL, OPTION_M32R},
   {"m32rx", no_argument, NULL, OPTION_M32RX},
+  {"m32r2", no_argument, NULL, OPTION_M32R2},
+  {"big", no_argument, NULL, OPTION_BIG},
+  {"little", no_argument, NULL, OPTION_LITTLE},
+  {"EB", no_argument, NULL, OPTION_BIG},
+  {"EL", no_argument, NULL, OPTION_LITTLE},
+  {"parallel", no_argument, NULL, OPTION_PARALLEL},
+  {"no-parallel", no_argument, NULL, OPTION_NO_PARALLEL},
   {"warn-explicit-parallel-conflicts", no_argument, NULL, OPTION_WARN_PARALLEL},
   {"Wp", no_argument, NULL, OPTION_WARN_PARALLEL},
   {"no-warn-explicit-parallel-conflicts", no_argument, NULL, OPTION_NO_WARN_PARALLEL},
   {"Wnp", no_argument, NULL, OPTION_NO_WARN_PARALLEL},
+  {"error-explicit-parallel-conflicts", no_argument, NULL, OPTION_ERROR_PARALLEL},
+  {"Ep", no_argument, NULL, OPTION_ERROR_PARALLEL},
+  {"no-error-explicit-parallel-conflicts", no_argument, NULL, OPTION_NO_ERROR_PARALLEL},
+  {"Enp", no_argument, NULL, OPTION_NO_ERROR_PARALLEL},
   {"hidden", no_argument, NULL, OPTION_SPECIAL},
+  {"bitinst", no_argument, NULL, OPTION_SPECIAL_M32R},
+  {"float", no_argument, NULL, OPTION_SPECIAL_FLOAT},
   /* Sigh.  I guess all warnings must now have both variants.  */
   {"warn-unmatched-high", no_argument, NULL, OPTION_WARN_UNMATCHED},
   {"Wuh", no_argument, NULL, OPTION_WARN_UNMATCHED},
@@ -195,15 +251,39 @@ struct option md_longopts[] =
 
 size_t md_longopts_size = sizeof (md_longopts);
 
+static void little (int);
+static int parallel (void);
+
+static void
+little (int on)
+{
+  target_big_endian = ! on;
+}
+
+/* Use parallel execution.  */
+
+static int
+parallel (void)
+{
+  if (! enable_m32rx)
+    return 0;
+
+  if (use_parallel == 1)
+    return 1;
+
+  return 0;
+}
+
 int
 md_parse_option (c, arg)
      int c;
-     char *arg;
+     char *arg ATTRIBUTE_UNUSED;
 {
   switch (c)
     {
     case 'O':
       optimize = 1;
+      use_parallel = 1;
       break;
 
     case OPTION_M32R:
@@ -214,11 +294,45 @@ md_parse_option (c, arg)
       allow_m32rx (1);
       break;
 
+    case OPTION_M32R2:
+      allow_m32rx (2);
+      enable_special = 1;
+      enable_special_m32r = 1;
+      break;
+
+    case OPTION_BIG:
+      target_big_endian = 1;
+      break;
+
+    case OPTION_LITTLE:
+      target_big_endian = 0;
+      break;
+
+    case OPTION_PARALLEL:
+      use_parallel = 1;
+      break;
+
+    case OPTION_NO_PARALLEL:
+      use_parallel = 0;
+      break;
+
     case OPTION_WARN_PARALLEL:
       warn_explicit_parallel_conflicts = 1;
+      error_explicit_parallel_conflicts = 0;
       break;
 
     case OPTION_NO_WARN_PARALLEL:
+      warn_explicit_parallel_conflicts = 0;
+      error_explicit_parallel_conflicts = 0;
+      break;
+
+    case OPTION_ERROR_PARALLEL:
+      warn_explicit_parallel_conflicts = 1;
+      error_explicit_parallel_conflicts = 1;
+      break;
+
+    case OPTION_NO_ERROR_PARALLEL:
+      error_explicit_parallel_conflicts = 0;
       warn_explicit_parallel_conflicts = 0;
       break;
 
@@ -233,6 +347,14 @@ md_parse_option (c, arg)
        }
       break;
 
+    case OPTION_SPECIAL_M32R:
+      enable_special_m32r = 1;
+      break;
+
+    case OPTION_SPECIAL_FLOAT:
+      enable_special_float = 1;
+      break;
+
     case OPTION_WARN_UNMATCHED:
       warn_unmatched_high = 1;
       break;
@@ -269,7 +391,17 @@ md_show_usage (stream)
   fprintf (stream, _("\
   -m32rx                  support the extended m32rx instruction set\n"));
   fprintf (stream, _("\
-  -O                      try to combine instructions in parallel\n"));
+  -m32r2                  support the extended m32r2 instruction set\n"));
+  fprintf (stream, _("\
+  -EL,-little             produce little endian code and data\n"));
+  fprintf (stream, _("\
+  -EB,-big                produce big endian code and data\n"));
+  fprintf (stream, _("\
+  -parallel               try to combine instructions in parallel\n"));
+  fprintf (stream, _("\
+  -no-parallel            disable -parallel\n"));
+  fprintf (stream, _("\
+  -O                      try to optimize code.  Implies -parallel\n"));
 
   fprintf (stream, _("\
   -warn-explicit-parallel-conflicts     warn when parallel instructions\n"));
@@ -283,6 +415,18 @@ md_show_usage (stream)
   -Wp                     synonym for -warn-explicit-parallel-conflicts\n"));
   fprintf (stream, _("\
   -Wnp                    synonym for -no-warn-explicit-parallel-conflicts\n"));
+  fprintf (stream, _("\
+  -error-explicit-parallel-conflicts     error when parallel instructions\n"));
+  fprintf (stream, _("\
+                                         violate contraints\n"));
+  fprintf (stream, _("\
+  -no-error-explicit-parallel-conflicts  do not error when parallel\n"));
+  fprintf (stream, _("\
+                                         instructions violate contraints\n"));
+  fprintf (stream, _("\
+  -Ep                     synonym for -error-explicit-parallel-conflicts\n"));
+  fprintf (stream, _("\
+  -Enp                    synonym for -no-error-explicit-parallel-conflicts\n"));
 
   fprintf (stream, _("\
   -warn-unmatched-high    warn when an (s)high reloc has no matching low reloc\n"));
@@ -317,14 +461,16 @@ const pseudo_typeS md_pseudo_table[] =
   { "fillinsn", fill_insn,     0 },
   { "scomm",   m32r_scomm,     0 },
   { "debugsym",        debug_sym,      0 },
-  /* Not documented as so far there is no need for them....  */
   { "m32r",    allow_m32rx,    0 },
   { "m32rx",   allow_m32rx,    1 },
+  { "m32r2",   allow_m32rx,    2 },
+  { "little",   little,         1 },
+  { "big",      little,         0 },
   { NULL, NULL, 0 }
 };
 
 /* FIXME: Should be machine generated.  */
-#define NOP_INSN 0x7000
+#define NOP_INSN     0x7000
 #define PAR_NOP_INSN 0xf000 /* Can only be used in 2nd slot.  */
 
 /* This is called from HANDLE_ALIGN in write.c.  Fill in the contents
@@ -379,7 +525,7 @@ m32r_handle_align (fragp)
 
 static void
 fill_insn (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   frag_align_code (2, 0);
   prev_insn.insn = NULL;
@@ -394,7 +540,7 @@ fill_insn (ignore)
 
 static void
 debug_sym (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   register char *name;
   register char delim;
@@ -444,7 +590,7 @@ expand_debug_syms (syms, align)
   if (!syms)
     return;
 
-  (void) m32r_do_align (align, NULL, 0, 0);
+  (void) frag_align_code (align, 0);
   for (; syms != (sym_linkS *) 0; syms = next_syms)
     {
       symbolS *symbolP = syms->symbol;
@@ -457,6 +603,16 @@ expand_debug_syms (syms, align)
   input_line_pointer = save_input_line;
 }
 
+void
+m32r_flush_pending_output()
+{
+  if (debug_sym_link)
+    {
+      expand_debug_syms (debug_sym_link, 1);
+      debug_sym_link = (sym_linkS *) 0;
+    }
+}
+
 /* Cover function to fill_insn called after a label and at end of assembly.
    The result is always 1: we're called in a conditional to see if the
    current line is a label.  */
@@ -486,6 +642,24 @@ m32r_fill_insn (done)
   return 1;
 }
 \f
+/* The default target format to use.  */
+
+const char *
+m32r_target_format ()
+{
+#ifdef TE_LINUX
+  if (target_big_endian)
+    return "elf32-m32r-linux";
+  else
+    return "elf32-m32rle-linux";
+#else
+  if (target_big_endian)
+    return "elf32-m32r";
+  else
+    return "elf32-m32rle";
+#endif
+}
+
 void
 md_begin ()
 {
@@ -498,7 +672,8 @@ md_begin ()
   /* Set the machine number and endian.  */
   gas_cgen_cpu_desc = m32r_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
                                          CGEN_CPU_OPEN_ENDIAN,
-                                         CGEN_ENDIAN_BIG,
+                                         (target_big_endian ?
+                                          CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE),
                                          CGEN_CPU_OPEN_END);
   m32r_cgen_init_asm (gas_cgen_cpu_desc);
 
@@ -554,6 +729,8 @@ md_begin ()
   scom_symbol.section         = &scom_section;
 
   allow_m32rx (enable_m32rx);
+
+  gas_cgen_initialize_saved_fixups_array ();
 }
 
 #define OPERAND_IS_COND_BIT(operand, indices, index) \
@@ -566,6 +743,9 @@ md_begin ()
    of instruction 'b'.  If 'check_outputs' is true then b's outputs are
    checked, otherwise its inputs are examined.  */
 
+static int first_writes_to_seconds_operands
+  PARAMS ((m32r_insn *, m32r_insn *, const int));
+
 static int
 first_writes_to_seconds_operands (a, b, check_outputs)
      m32r_insn *a;
@@ -640,6 +820,8 @@ first_writes_to_seconds_operands (a, b, check_outputs)
 
 /* Returns true if the insn can (potentially) alter the program counter.  */
 
+static int writes_to_pc PARAMS ((m32r_insn *));
+
 static int
 writes_to_pc (a)
      m32r_insn *a;
@@ -672,6 +854,8 @@ writes_to_pc (a)
 /* Return NULL if the two 16 bit insns can be executed in parallel.
    Otherwise return a pointer to an error message explaining why not.  */
 
+static const char *can_make_parallel PARAMS ((m32r_insn *, m32r_insn *));
+
 static const char *
 can_make_parallel (a, b)
      m32r_insn *a;
@@ -685,7 +869,7 @@ can_make_parallel (a, b)
       || CGEN_FIELDS_BITSIZE (&b->fields) != 16)
     abort ();
 
-  if (first_writes_to_seconds_operands (a, b, true))
+  if (first_writes_to_seconds_operands (a, b, TRUE))
     return _("Instructions write to the same destination register.");
 
   a_pipe = CGEN_INSN_ATTR_VALUE (a->insn, CGEN_INSN_PIPE);
@@ -700,7 +884,8 @@ can_make_parallel (a, b)
      go away if the instructions are swapped, and we want to make
      sure that any other errors are detected before this happens.  */
   if (a_pipe == PIPE_S
-      || b_pipe == PIPE_O)
+      || b_pipe == PIPE_O
+      || (b_pipe == PIPE_O_OS && (enable_m32rx != 2)))
     return _("Instructions share the same execution pipeline");
 
   return NULL;
@@ -708,6 +893,8 @@ can_make_parallel (a, b)
 
 /* Force the top bit of the second 16-bit insn to be set.  */
 
+static void make_parallel PARAMS ((CGEN_INSN_BYTES_PTR));
+
 static void
 make_parallel (buffer)
      CGEN_INSN_BYTES_PTR buffer;
@@ -722,6 +909,8 @@ make_parallel (buffer)
 
 /* Same as make_parallel except buffer contains the bytes in target order.  */
 
+static void target_make_parallel PARAMS ((char *));
+
 static void
 target_make_parallel (buffer)
      char *buffer;
@@ -733,6 +922,8 @@ target_make_parallel (buffer)
 /* Assemble two instructions with an explicit parallel operation (||) or
    sequential operation (->).  */
 
+static void assemble_two_insns PARAMS ((char *, char *, int));
+
 static void
 assemble_two_insns (str, str2, parallel_p)
      char *str;
@@ -745,7 +936,7 @@ assemble_two_insns (str, str2, parallel_p)
   char *errmsg;
   char save_str2 = *str2;
 
-  /* Seperate the two instructions.  */
+  /* Separate the two instructions.  */
   *str2 = 0;
 
   /* Make sure the two insns begin on a 32 bit boundary.
@@ -774,8 +965,26 @@ assemble_two_insns (str, str2, parallel_p)
       as_bad (_("not a 16 bit instruction '%s'"), str);
       return;
     }
+#ifdef E_M32R2_ARCH
+  else if ((enable_m32rx == 1)
+           /* FIXME: Need standard macro to perform this test.  */
+           && ((CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_MACH)
+                & (1 << MACH_M32R2))
+               && !((CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_MACH)
+                    & (1 << MACH_M32RX)))))
+    {
+      /* xgettext:c-format  */
+      as_bad (_("instruction '%s' is for the M32R2 only"), str);
+      return;
+    }
+  else if ((! enable_special
+            && CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_SPECIAL))
+           || (! enable_special_m32r
+               && CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_SPECIAL_M32R)))
+#else
   else if (! enable_special
       && CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_SPECIAL))
+#endif
     {
       /* xgettext:c-format  */
       as_bad (_("unknown instruction '%s'"), str);
@@ -817,22 +1026,21 @@ assemble_two_insns (str, str2, parallel_p)
   {
     char *s2 = str;
 
-    while (isspace (*s2++))
+    while (ISSPACE (*s2++))
       continue;
 
     --s2;
 
-    while (isalnum (*s2))
+    while (ISALNUM (*s2))
       {
-       if (isupper ((unsigned char) *s2))
-         *s2 = tolower (*s2);
+       *s2 = TOLOWER (*s2);
        s2++;
       }
   }
 
   /* Preserve any fixups that have been generated and reset the list
      to empty.  */
-  gas_cgen_save_fixups ();
+  gas_cgen_save_fixups (0);
 
   /* Get the indices of the operands of the instruction.  */
   /* FIXME: CGEN_FIELDS is already recorded, but relying on that fact
@@ -871,8 +1079,26 @@ assemble_two_insns (str, str2, parallel_p)
       as_bad (_("not a 16 bit instruction '%s'"), str);
       return;
     }
+#ifdef E_M32R2_ARCH
+  else if ((enable_m32rx == 1)
+           /* FIXME: Need standard macro to perform this test.  */
+           && ((CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_MACH)
+                & (1 << MACH_M32R2))
+               && !((CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_MACH)
+                    & (1 << MACH_M32RX)))))
+    {
+      /* xgettext:c-format  */
+      as_bad (_("instruction '%s' is for the M32R2 only"), str);
+      return;
+    }
+  else if ((! enable_special
+            && CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_SPECIAL))
+           || (! enable_special_m32r
+               && CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_SPECIAL_M32R)))
+#else
   else if (! enable_special
       && CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_SPECIAL))
+#endif
     {
       /* xgettext:c-format  */
       as_bad (_("unknown instruction '%s'"), str);
@@ -928,20 +1154,24 @@ assemble_two_insns (str, str2, parallel_p)
 
   if (parallel_p && warn_explicit_parallel_conflicts)
     {
-      if (first_writes_to_seconds_operands (&first, &second, false))
+      void (* func)(const char *, ...);
+
+      func = error_explicit_parallel_conflicts ? as_bad : as_warn;
+
+      if (first_writes_to_seconds_operands (&first, &second, FALSE))
        /* xgettext:c-format  */
-       as_warn (_("%s: output of 1st instruction is the same as an input to 2nd instruction - is this intentional ?"), str2);
+       func (_("%s: output of 1st instruction is the same as an input to 2nd instruction - is this intentional ?"), str2);
 
-      if (first_writes_to_seconds_operands (&second, &first, false))
+      if (first_writes_to_seconds_operands (&second, &first, FALSE))
        /* xgettext:c-format  */
-       as_warn (_("%s: output of 2nd instruction is the same as an input to 1st instruction - is this intentional ?"), str2);
+       func (_("%s: output of 2nd instruction is the same as an input to 1st instruction - is this intentional ?"), str2);
     }
 
   if (!parallel_p
       || (errmsg = (char *) can_make_parallel (&first, &second)) == NULL)
     {
       /* Get the fixups for the first instruction.  */
-      gas_cgen_swap_fixups ();
+      gas_cgen_swap_fixups (0);
 
       /* Write it out.  */
       expand_debug_syms (first.debug_sym_link, 1);
@@ -953,7 +1183,7 @@ assemble_two_insns (str, str2, parallel_p)
        make_parallel (second.buffer);
 
       /* Get its fixups.  */
-      gas_cgen_restore_fixups ();
+      gas_cgen_restore_fixups (0);
 
       /* Write it out.  */
       expand_debug_syms (second.debug_sym_link, 1);
@@ -972,7 +1202,7 @@ assemble_two_insns (str, str2, parallel_p)
       make_parallel (first.buffer);
 
       /* Get the fixups for the first instruction.  */
-      gas_cgen_restore_fixups ();
+      gas_cgen_restore_fixups (0);
 
       /* Write out the first instruction.  */
       expand_debug_syms (first.debug_sym_link, 1);
@@ -985,6 +1215,16 @@ assemble_two_insns (str, str2, parallel_p)
       return;
     }
 
+  if (CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_SPECIAL)
+      || CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_SPECIAL))
+    m32r_flags |= E_M32R_HAS_HIDDEN_INST;
+  if (CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_SPECIAL_M32R)
+      || CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_SPECIAL_M32R))
+    m32r_flags |= E_M32R_HAS_BIT_INST;
+  if (CGEN_INSN_ATTR_VALUE (first.insn, CGEN_INSN_SPECIAL_FLOAT)
+      || CGEN_INSN_ATTR_VALUE (second.insn, CGEN_INSN_SPECIAL_FLOAT))
+    m32r_flags |= E_M32R_HAS_FLOAT_INST;
+
   /* Set these so m32r_fill_insn can use them.  */
   prev_seg    = now_seg;
   prev_subseg = now_subseg;
@@ -1001,14 +1241,15 @@ md_assemble (str)
   /* Initialize GAS's cgen interface for a new instruction.  */
   gas_cgen_init_parse ();
 
-  /* Look for a parallel instruction seperator.  */
+  /* Look for a parallel instruction separator.  */
   if ((str2 = strstr (str, "||")) != NULL)
     {
       assemble_two_insns (str, str2, 1);
+      m32r_flags |= E_M32R_HAS_PARALLEL;
       return;
     }
 
-  /* Also look for a sequential instruction seperator.  */
+  /* Also look for a sequential instruction separator.  */
   if ((str2 = strstr (str, "->")) != NULL)
     {
       assemble_two_insns (str, str2, 0);
@@ -1027,8 +1268,26 @@ md_assemble (str)
       return;
     }
 
+#ifdef E_M32R2_ARCH
+  if ((enable_m32rx == 1)
+       /* FIXME: Need standard macro to perform this test.  */
+      && ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MACH)
+           & (1 << MACH_M32R2))
+          && !((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MACH)
+               & (1 << MACH_M32RX)))))
+    {
+      /* xgettext:c-format  */
+      as_bad (_("instruction '%s' is for the M32R2 only"), str);
+      return;
+    }
+  else if ((! enable_special
+       && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SPECIAL))
+      || (! enable_special_m32r
+          && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SPECIAL_M32R)))
+#else
   if (! enable_special
       && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SPECIAL))
+#endif
     {
       /* xgettext:c-format  */
       as_bad (_("unknown instruction '%s'"), str);
@@ -1042,6 +1301,13 @@ md_assemble (str)
       return;
     }
 
+  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SPECIAL))
+    m32r_flags |= E_M32R_HAS_HIDDEN_INST;
+  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SPECIAL_M32R))
+    m32r_flags |= E_M32R_HAS_BIT_INST;
+  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SPECIAL_FLOAT))
+    m32r_flags |= E_M32R_HAS_FLOAT_INST;
+
   if (CGEN_INSN_BITSIZE (insn.insn) == 32)
     {
       /* 32 bit insns must live on 32 bit boundaries.  */
@@ -1062,7 +1328,7 @@ md_assemble (str)
   else
     {
       int on_32bit_boundary_p;
-      int swap = false;
+      int swap = FALSE;
 
       if (CGEN_INSN_BITSIZE (insn.insn) != 16)
        abort ();
@@ -1106,16 +1372,15 @@ md_assemble (str)
         Otherwise call can_make_parallel() with both orderings of the
         instructions to see if they can be combined.  */
       if (! on_32bit_boundary_p
-         && enable_m32rx
-         && optimize
+         && parallel ()
          && CGEN_INSN_ATTR_VALUE (insn.orig_insn, CGEN_INSN_RELAXABLE) == 0
          && ! writes_to_pc (&prev_insn)
-         && ! first_writes_to_seconds_operands (&prev_insn, &insn, false))
+         && ! first_writes_to_seconds_operands (&prev_insn, &insn, FALSE))
        {
          if (can_make_parallel (&prev_insn, &insn) == NULL)
            make_parallel (insn.buffer);
          else if (can_make_parallel (&insn, &prev_insn) == NULL)
-           swap = true;
+           swap = TRUE;
        }
 
       expand_debug_syms (insn.debug_sym_link, 1);
@@ -1215,7 +1480,7 @@ md_section_align (segment, size)
 
 symbolS *
 md_undefined_symbol (name)
-     char *name;
+     char *name ATTRIBUTE_UNUSED;
 {
   return 0;
 }
@@ -1229,7 +1494,7 @@ md_undefined_symbol (name)
 
 static void
 m32r_scomm (ignore)
-     int ignore;
+     int ignore ATTRIBUTE_UNUSED;
 {
   register char *name;
   register char c;
@@ -1384,7 +1649,8 @@ const relax_typeS md_relax_table[] =
 };
 
 long
-m32r_relax_frag (fragP, stretch)
+m32r_relax_frag (segment, fragP, stretch)
+     segT segment;
      fragS *fragP;
      long stretch;
 {
@@ -1411,7 +1677,7 @@ m32r_relax_frag (fragP, stretch)
     }
   else
     {
-      growth = relax_frag (fragP, stretch);
+      growth = relax_frag (segment, fragP, stretch);
 
       /* Long jump on odd halfword boundary?  */
       if (fragP->fr_subtype == 2 && (address & 3) != 0)
@@ -1440,8 +1706,6 @@ md_estimate_size_before_relax (fragP, segment)
      fragS *fragP;
      segT segment;
 {
-  int old_fr_fix = fragP->fr_fix;
-
   /* The only thing we have to handle here are symbols outside of the
      current segment.  They may be undefined or in a different segment in
      which case linker scripts may place them anywhere.
@@ -1450,6 +1714,10 @@ md_estimate_size_before_relax (fragP, segment)
 
   if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
     {
+#if 0
+      int old_fr_fix = fragP->fr_fix;
+#endif
+
       /* The symbol is undefined in this segment.
         Change the relaxation subtype to the max allowable and leave
         all further handling to md_convert_frag.  */
@@ -1473,6 +1741,7 @@ md_estimate_size_before_relax (fragP, segment)
 
       /* Mark this fragment as finished.  */
       frag_wane (fragP);
+      return fragP->fr_fix - old_fr_fix;
 #else
       {
        const CGEN_INSN *insn;
@@ -1487,7 +1756,7 @@ md_estimate_size_before_relax (fragP, segment)
            if ((strcmp (CGEN_INSN_MNEMONIC (insn),
                         CGEN_INSN_MNEMONIC (fragP->fr_cgen.insn))
                 == 0)
-               && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX))
+               && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
              break;
          }
        if (i == 4)
@@ -1499,7 +1768,7 @@ md_estimate_size_before_relax (fragP, segment)
 #endif
     }
 
-  return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
+  return md_relax_table[fragP->fr_subtype].rlx_length;
 }
 
 /* *FRAGP has been relaxed to its final size, and now needs to have
@@ -1511,7 +1780,7 @@ md_estimate_size_before_relax (fragP, segment)
 
 void
 md_convert_frag (abfd, sec, fragP)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      segT sec;
      fragS *fragP;
 {
@@ -1560,7 +1829,6 @@ md_convert_frag (abfd, sec, fragP)
     {
       /* Address we want to reach in file space.  */
       target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
-      target_address += symbol_get_frag (fragP->fr_symbol)->fr_address;
       addend = (target_address - (opcode_address & -4)) >> 2;
     }
 
@@ -1624,7 +1892,7 @@ md_pcrel_from_section (fixP, sec)
 
 bfd_reloc_code_real_type
 md_cgen_lookup_reloc (insn, operand, fixP)
-     const CGEN_INSN *insn;
+     const CGEN_INSN *insn ATTRIBUTE_UNUSED;
      const CGEN_OPERAND *operand;
      fixS *fixP;
 {
@@ -1650,11 +1918,13 @@ md_cgen_lookup_reloc (insn, operand, fixP)
 
 /* Record a HI16 reloc for later matching with its LO16 cousin.  */
 
+static void m32r_record_hi16 PARAMS ((int, fixS *, segT));
+
 static void
 m32r_record_hi16 (reloc_type, fixP, seg)
      int reloc_type;
      fixS *fixP;
-     segT seg;
+     segT seg ATTRIBUTE_UNUSED;
 {
   struct m32r_hi_fixup *hi_fixup;
 
@@ -1708,7 +1978,7 @@ m32r_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
 #define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo)
 
 /* Sort any unmatched HI16 relocs so that they immediately precede
-   the corresponding LO16 reloc.  This is called before md_apply_fix and
+   the corresponding LO16 reloc.  This is called before md_apply_fix3 and
    tc_gen_reloc.  */
 
 void
@@ -1797,8 +2067,7 @@ int
 m32r_force_relocation (fix)
      fixS *fix;
 {
-  if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
-      || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+  if (generic_force_reloc (fix))
     return 1;
 
   if (! m32r_relax)
@@ -1839,7 +2108,6 @@ md_atof (type, litP, sizeP)
   int prec;
   LITTLENUM_TYPE words[MAX_LITTLENUMS];
   char *t;
-  char *atof_ieee ();
 
   switch (type)
     {
@@ -1906,11 +2174,10 @@ m32r_elf_section_change_hook ()
 /* Return true if can adjust the reloc to be relative to its section
    (such as .data) instead of relative to some symbol.  */
 
-boolean
+bfd_boolean
 m32r_fix_adjustable (fixP)
    fixS *fixP;
 {
-
   bfd_reloc_code_real_type reloc_type;
 
   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
@@ -1924,15 +2191,6 @@ m32r_fix_adjustable (fixP)
   else
     reloc_type = fixP->fx_r_type;
 
-  if (fixP->fx_addsy == NULL)
-    return 1;
-
-  /* Prevent all adjustments to global symbols.  */
-  if (S_IS_EXTERN (fixP->fx_addsy))
-    return 0;
-  if (S_IS_WEAK (fixP->fx_addsy))
-    return 0;
-
   /* We need the symbol name for the VTABLE entries.  */
   if (reloc_type == BFD_RELOC_VTABLE_INHERIT
       || reloc_type == BFD_RELOC_VTABLE_ENTRY)
@@ -1940,3 +2198,11 @@ m32r_fix_adjustable (fixP)
 
   return 1;
 }
+
+void
+m32r_elf_final_processing ()
+{
+  if (use_parallel)
+    m32r_flags |= E_M32R_HAS_PARALLEL;
+  elf_elfheader (stdoutput)->e_flags |= m32r_flags;
+}
This page took 0.033858 seconds and 4 git commands to generate.