Add Nios II arch flags and compatibility tests
[deliverable/binutils-gdb.git] / gas / config / tc-nios2.c
index 3ed7a9e2b146453426fad9f432a2a211fe15c43f..549ca98f5f7c5de085536e8e683a671582683fad 100644 (file)
@@ -1,5 +1,5 @@
 /* Altera Nios II assembler.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Contributed by Nigel Gray (ngray@altera.com).
    Contributed by Mentor Graphics, Inc.
 
@@ -25,6 +25,7 @@
 #include "elf/nios2.h"
 #include "tc-nios2.h"
 #include "bfd.h"
+#include "libbfd.h"
 #include "dwarf2dbg.h"
 #include "subsegs.h"
 #include "safe-ctype.h"
@@ -80,7 +81,9 @@ struct option md_longopts[] = {
 #define OPTION_EB (OPTION_MD_BASE + 3)
   {"EB", no_argument, NULL, OPTION_EB},
 #define OPTION_EL (OPTION_MD_BASE + 4)
-  {"EL", no_argument, NULL, OPTION_EL}
+  {"EL", no_argument, NULL, OPTION_EL},
+#define OPTION_MARCH (OPTION_MD_BASE + 5)
+  {"march", required_argument, NULL, OPTION_MARCH}
 };
 
 size_t md_longopts_size = sizeof (md_longopts);
@@ -212,6 +215,9 @@ static symbolS *nios2_last_label;
 symbolS *GOT_symbol;
 #endif
 
+/* The processor architecture value, EF_NIOS2_ARCH_R1 by default.  */
+static int nios2_architecture = EF_NIOS2_ARCH_R1;
+
 \f
 /** Utility routines.  */
 /* Function md_chars_to_number takes the sequence of
@@ -1033,7 +1039,7 @@ nios2_diagnose_overflow (valueT fixup, reloc_howto_type *howto,
       unsigned int range_max;
       unsigned int address;
 
-      opcode = nios2_find_opcode_hash (value);
+      opcode = nios2_find_opcode_hash (value, bfd_get_mach (stdoutput));
       gas_assert (opcode);
       gas_assert (fixP->fx_size == opcode->size);
       overflow_msg_type = opcode->overflow_msg;
@@ -2062,34 +2068,6 @@ const int nios2_num_ps_insn_info_structs = NIOS2_NUM_PSEUDO_INSNS;
 \f
 /** Assembler output support.  */
 
-static int
-can_evaluate_expr (nios2_insn_infoS *insn)
-{
-  /* Remove this check for null and the invalid insn "ori r9, 1234" seg faults. */
-  if (!insn->insn_reloc) 
-    /* ??? Ideally we should do something other than as_fatal here as we can
-       continue to assemble.
-       However this function (actually the output_* functions) should not 
-       have been called in the first place once an illegal instruction had 
-       been encountered.  */
-    as_fatal (_("Invalid instruction encountered, cannot recover. No assembly attempted."));
-
-  if (insn->insn_reloc->reloc_expression.X_op == O_constant)
-    return 1;
-
-  return 0;
-}
-
-static int
-get_expr_value (nios2_insn_infoS *insn)
-{
-  int value = 0;
-
-  if (insn->insn_reloc->reloc_expression.X_op == O_constant)
-    value = insn->insn_reloc->reloc_expression.X_add_number;
-  return value;
-}
-
 /* Output a normal instruction.  */
 static void
 output_insn (nios2_insn_infoS *insn)
@@ -2203,107 +2181,6 @@ output_call (nios2_insn_infoS *insn)
   dwarf2_emit_insn (4);
 }
 
-/* Output an addi - will silently convert to
-   orhi if rA = r0 and (expr & 0xffff0000) == 0.  */
-static void
-output_addi (nios2_insn_infoS *insn)
-{
-  if (can_evaluate_expr (insn))
-    {
-      int expr_val = get_expr_value (insn);
-      unsigned int rega = GET_IW_I_A (insn->insn_code);
-      unsigned int regb = GET_IW_I_B (insn->insn_code);
-
-      if (rega == 0
-         && (expr_val & 0xffff) == 0
-         && expr_val != 0)
-       {
-         /* We really want a movhi (orhi) here.  */
-         insn->insn_code
-           = MATCH_R1_ORHI | SET_IW_I_A (rega) | SET_IW_I_B (regb);
-         insn->insn_reloc->reloc_expression.X_add_number
-           = (expr_val >> 16) & 0xffff;
-         insn->insn_reloc->reloc_type = BFD_RELOC_NIOS2_U16;
-       }
-    }
-
-  /* Output an instruction.  */
-  output_insn (insn);
-}
-
-static void
-output_andi (nios2_insn_infoS *insn)
-{
-  if (can_evaluate_expr (insn))
-    {
-      int expr_val = get_expr_value (insn);
-      if (expr_val != 0 && (expr_val & 0xffff) == 0)
-       {
-         unsigned int rega = GET_IW_I_A (insn->insn_code);
-         unsigned int regb = GET_IW_I_B (insn->insn_code);
-
-         /* We really want an andhi here.  */
-         insn->insn_code
-           = MATCH_R1_ANDHI | SET_IW_I_A (rega) | SET_IW_I_B (regb);
-         insn->insn_reloc->reloc_expression.X_add_number
-           = (expr_val >> 16) & 0xffff;
-         insn->insn_reloc->reloc_type = BFD_RELOC_NIOS2_U16;
-       }
-    }
-
-  /* Output an instruction.  */
-  output_insn (insn);
-}
-
-static void
-output_ori (nios2_insn_infoS *insn)
-{
-  if (can_evaluate_expr (insn))
-    {
-      int expr_val = get_expr_value (insn);
-      if (expr_val != 0 && (expr_val & 0xffff) == 0)
-       {
-         unsigned int rega = GET_IW_I_A (insn->insn_code);
-         unsigned int regb = GET_IW_I_B (insn->insn_code);
-
-         /* We really want a movhi (orhi) here.  */
-         insn->insn_code
-           = MATCH_R1_ORHI | SET_IW_I_A (rega) | SET_IW_I_B (regb);
-         insn->insn_reloc->reloc_expression.X_add_number
-           = (expr_val >> 16) & 0xffff;
-         insn->insn_reloc->reloc_type = BFD_RELOC_NIOS2_U16;
-       }
-    }
-
-  /* Output an instruction.  */
-  output_insn (insn);
-}
-
-static void
-output_xori (nios2_insn_infoS *insn)
-{
-  if (can_evaluate_expr (insn))
-    {
-      int expr_val = get_expr_value (insn);
-      if (expr_val != 0 && (expr_val & 0xffff) == 0)
-       {
-         unsigned int rega = GET_IW_I_A (insn->insn_code);
-         unsigned int regb = GET_IW_I_B (insn->insn_code);
-
-         /* We really want an xorhi here.  */
-         insn->insn_code
-           = MATCH_R1_XORHI | SET_IW_I_A (rega) | SET_IW_I_B (regb);
-         insn->insn_reloc->reloc_expression.X_add_number
-           = (expr_val >> 16) & 0xffff;
-         insn->insn_reloc->reloc_type = BFD_RELOC_NIOS2_U16;
-       }
-    }
-
-  /* Output an instruction.  */
-  output_insn (insn);
-}
-
-
 /* Output a movhi/addi pair for the movia pseudo-op.  */
 static void
 output_movia (nios2_insn_infoS *insn)
@@ -2338,6 +2215,34 @@ output_movia (nios2_insn_infoS *insn)
 \f
 /** External interfaces.  */
 
+/* Update the selected architecture based on ARCH, giving an error if
+   ARCH is an invalid value.  */
+
+static void
+nios2_use_arch (const char *arch)
+{
+  if (strcmp (arch, "nios2") == 0 || strcmp (arch, "r1") == 0)
+    {
+      nios2_architecture |= EF_NIOS2_ARCH_R1;
+      nios2_opcodes = (struct nios2_opcode *) nios2_r1_opcodes;
+      nios2_num_opcodes = nios2_num_r1_opcodes;
+      nop32 = nop_r1;
+      nop16 = NULL;
+      return;
+    }
+  else if (strcmp (arch, "r2") == 0)
+    {
+      nios2_architecture |= EF_NIOS2_ARCH_R2;
+      nios2_opcodes = (struct nios2_opcode *) nios2_r2_opcodes;
+      nios2_num_opcodes = nios2_num_r2_opcodes;
+      nop32 = nop_r2;
+      nop16 = nop_r2_cdx;
+      return;
+    }
+
+  as_bad (_("unknown architecture '%s'"), arch);
+}
+
 /* The following functions are called by machine-independent parts of
    the assembler. */
 int
@@ -2364,6 +2269,9 @@ md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
     case OPTION_EL:
       target_big_endian = 0;
       break;
+    case OPTION_MARCH:
+      nios2_use_arch (arg);
+      break;
     default:
       return 0;
       break;
@@ -2391,9 +2299,11 @@ md_show_usage (FILE *stream)
           "branches with jmp sequences (default)\n"
           "  -no-relax             do not replace any branches or calls\n"
           "  -EB                   force big-endian byte ordering\n"
-          "  -EL                   force little-endian byte ordering\n");
+          "  -EL                   force little-endian byte ordering\n"
+          "  -march=ARCH           enable instructions from architecture ARCH\n");
 }
 
+
 /* This function is called once, at assembler startup time.
    It should set up all the tables, etc. that the MD part of the
    assembler will need. */
@@ -2403,6 +2313,19 @@ md_begin (void)
   int i;
   const char *inserted;
 
+  switch (nios2_architecture)
+    {
+    default:
+    case EF_NIOS2_ARCH_R1:
+      bfd_default_set_arch_mach (stdoutput, bfd_arch_nios2, bfd_mach_nios2r1);
+      break;
+    case EF_NIOS2_ARCH_R2:
+      if (target_big_endian)
+       as_fatal (_("Big-endian R2 is not supported."));
+      bfd_default_set_arch_mach (stdoutput, bfd_arch_nios2, bfd_mach_nios2r2);
+      break;
+    }
+
   /* Create and fill a hashtable for the Nios II opcodes, registers and 
      arguments.  */
   nios2_opcode_hash = hash_new ();
@@ -2540,14 +2463,6 @@ md_assemble (char *op_str)
                   || (insn->insn_reloc->reloc_type
                       == BFD_RELOC_NIOS2_CALL26_NOAT)))
        output_call (insn);
-      else if (insn->insn_nios2_opcode->pinfo & NIOS2_INSN_ANDI)
-       output_andi (insn);
-      else if (insn->insn_nios2_opcode->pinfo & NIOS2_INSN_ORI)
-       output_ori (insn);
-      else if (insn->insn_nios2_opcode->pinfo & NIOS2_INSN_XORI)
-       output_xori (insn);
-      else if (insn->insn_nios2_opcode->pinfo & NIOS2_INSN_ADDI)
-       output_addi (insn);
       else if (saved_pinfo == NIOS2_INSN_MACRO_MOVIA)
        output_movia (insn);
       else
@@ -2884,3 +2799,13 @@ nios2_frame_initial_instructions (void)
 {
   cfi_add_CFA_def_cfa (27, 0);
 }
+
+#ifdef OBJ_ELF
+/* Some special processing for a Nios II ELF file.  */
+
+void
+nios2_elf_final_processing (void)
+{
+  elf_elfheader (stdoutput)->e_flags = nios2_architecture;
+}
+#endif
This page took 0.02657 seconds and 4 git commands to generate.