/* 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.
#include "elf/nios2.h"
#include "tc-nios2.h"
#include "bfd.h"
+#include "libbfd.h"
#include "dwarf2dbg.h"
#include "subsegs.h"
#include "safe-ctype.h"
#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);
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
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;
\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)
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)
\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
case OPTION_EL:
target_big_endian = 0;
break;
+ case OPTION_MARCH:
+ nios2_use_arch (arg);
+ break;
default:
return 0;
break;
"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. */
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 ();
|| (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
{
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