/* tc-v850.c -- Assembler code for the NEC V850
- Copyright (C) 1996-2015 Free Software Foundation, Inc.
+ Copyright (C) 1996-2020 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
static bfd_boolean warn_signed_overflows = FALSE;
static bfd_boolean warn_unsigned_overflows = FALSE;
+/* Non-zero if floating point insns are not being used. */
+static signed int soft_float = -1;
+
/* Indicates the target BFD machine number. */
static int machine = -1;
-/* Indiciates the target BFD architecture. */
-int v850_target_arch = bfd_arch_v850_rh850;
+/* Indicates the target BFD architecture. */
+enum bfd_architecture v850_target_arch = bfd_arch_v850_rh850;
const char * v850_target_format = "elf32-v850-rh850";
static flagword v850_e_flags = 0;
else
{
seg->s = subseg_new (seg->name, sub);
- bfd_set_section_flags (stdoutput, seg->s, seg->flags);
+ bfd_set_section_flags (seg->s, seg->flags);
if ((seg->flags & SEC_LOAD) == 0)
seg_info (seg->s)->bss = 1;
}
symbolS *symbolP;
int have_align;
- name = input_line_pointer;
- c = get_symbol_end ();
+ c = get_symbol_name (&name);
/* Just after name is now '\0'. */
p = input_line_pointer;
(sizeof (vector_registers) / sizeof (struct reg_name))
/* Do a binary search of the given register table to see if NAME is a
- valid regiter name. Return the register number from the array on
+ valid register name. Return the register number from the array on
success, or -1 on failure. */
static int
char c;
/* Find the spelling of the operand. */
- start = name = input_line_pointer;
-
- c = get_symbol_end ();
+ start = input_line_pointer;
+ c = get_symbol_name (&name);
reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT,
name, FALSE);
/* Put back the delimiting char. */
- *input_line_pointer = c;
+ (void) restore_line_pointer (c);
expressionP->X_add_symbol = NULL;
expressionP->X_op_symbol = NULL;
char c;
/* Find the spelling of the operand. */
- start = name = input_line_pointer;
-
- c = get_symbol_end ();
+ start = input_line_pointer;
+ c = get_symbol_name (&name);
reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name,
accept_numbers);
/* Put back the delimiting char. */
- *input_line_pointer = c;
+ (void) restore_line_pointer (c);
if (reg_number < 0
&& accept_numbers)
char c;
/* Find the spelling of the operand. */
- start = name = input_line_pointer;
-
- c = get_symbol_end ();
+ start = input_line_pointer;
+ c = get_symbol_name (&name);
reg_number = reg_name_search (cc_names, CC_NAME_CNT, name, accept_numbers);
/* Put back the delimiting char. */
- *input_line_pointer = c;
+ (void) restore_line_pointer (c);
if (reg_number < 0
&& accept_numbers)
char c;
/* Find the spelling of the operand. */
- start = name = input_line_pointer;
-
- c = get_symbol_end ();
+ start = input_line_pointer;
+ c = get_symbol_name (&name);
reg_number = reg_name_search (float_cc_names, FLOAT_CC_NAME_CNT, name, accept_numbers);
/* Put back the delimiting char. */
- *input_line_pointer = c;
+ (void) restore_line_pointer (c);
if (reg_number < 0
&& accept_numbers)
char c;
/* Find the spelling of the operand. */
- start = name = input_line_pointer;
-
- c = get_symbol_end ();
+ start = input_line_pointer;
+ c = get_symbol_name (&name);
reg_number = reg_name_search (cacheop_names, CACHEOP_NAME_CNT, name, accept_numbers);
/* Put back the delimiting char. */
- *input_line_pointer = c;
+ (void) restore_line_pointer (c);
if (reg_number < 0
&& accept_numbers)
char c;
/* Find the spelling of the operand. */
- start = name = input_line_pointer;
-
- c = get_symbol_end ();
+ start = input_line_pointer;
+ c = get_symbol_name (&name);
reg_number = reg_name_search (prefop_names, PREFOP_NAME_CNT, name, accept_numbers);
/* Put back the delimiting char. */
- *input_line_pointer = c;
+ (void) restore_line_pointer (c);
if (reg_number < 0
&& accept_numbers)
char c;
/* Find the spelling of the operand. */
- start = name = input_line_pointer;
-
- c = get_symbol_end ();
+ start = input_line_pointer;
+ c = get_symbol_name (&name);
reg_number = reg_name_search (vector_registers, VREG_NAME_CNT,
name, FALSE);
/* Put back the delimiting char. */
- *input_line_pointer = c;
+ (void) restore_line_pointer (c);
expressionP->X_add_symbol = NULL;
expressionP->X_op_symbol = NULL;
{ rX - rY, rZ }
etc
- and also parses constant expressions whoes bits indicate the
+ and also parses constant expressions whose bits indicate the
registers in the lists. The LSB in the expression refers to
the lowest numbered permissible register in the register list,
and so on upwards. System registers are considered to be very
high numbers. */
-static char *
+static const char *
parse_register_list (unsigned long *insn,
const struct v850_operand *operand)
{
skip_white_space ();
/* If the expression starts with a curly brace it is a register list.
- Otherwise it is a constant expression, whoes bits indicate which
+ Otherwise it is a constant expression, whose bits indicate which
registers are to be included in the list. */
if (*input_line_pointer != '{')
{
size_t md_longopts_size = sizeof (md_longopts);
+static bfd_boolean v850_data_8 = FALSE;
+
void
md_show_usage (FILE *stream)
{
fprintf (stream, _(" -mrh850-abi Mark the binary as using the RH850 ABI (default)\n"));
fprintf (stream, _(" -m8byte-align Mark the binary as using 64-bit alignment\n"));
fprintf (stream, _(" -m4byte-align Mark the binary as using 32-bit alignment (default)\n"));
+ fprintf (stream, _(" -msoft-float Mark the binary as not using FP insns (default for pre e2v3)\n"));
+ fprintf (stream, _(" -mhard-float Mark the binary as using FP insns (default for e2v3 and up)\n"));
}
int
-md_parse_option (int c, char *arg)
+md_parse_option (int c, const char *arg)
{
if (c != 'm')
{
v850_target_format = "elf32-v850-rh850";
}
else if (strcmp (arg, "8byte-align") == 0)
- v850_e_flags |= EF_RH850_DATA_ALIGN8;
+ {
+ v850_data_8 = TRUE;
+ v850_e_flags |= EF_RH850_DATA_ALIGN8;
+ }
else if (strcmp (arg, "4byte-align") == 0)
- v850_e_flags &= ~ EF_RH850_DATA_ALIGN8;
+ {
+ v850_data_8 = FALSE;
+ v850_e_flags &= ~ EF_RH850_DATA_ALIGN8;
+ }
+ else if (strcmp (arg, "soft-float") == 0)
+ soft_float = 1;
+ else if (strcmp (arg, "hard-float") == 0)
+ soft_float = 0;
else
return 0;
return 0;
}
-char *
+const char *
md_atof (int type, char *litp, int *sizep)
{
return ieee_md_atof (type, litp, sizep, FALSE);
else if (fragP->fr_subtype == SUBYPTE_LOOP_16_22 + 1)
{
unsigned char * buffer =
- (unsigned char *) (fragP->fr_fix + fragP->fr_literal);
+ (unsigned char *) (fragP->fr_fix + &fragP->fr_literal[0]);
int loop_reg = (buffer[0] & 0x1f);
/* Add -1.reg. */
|| fragP->fr_subtype == SUBYPTE_SA_9_17_22_32 + 1)
{
unsigned char *buffer =
- (unsigned char *) (fragP->fr_fix + fragP->fr_literal);
+ (unsigned char *) (fragP->fr_fix + &fragP->fr_literal[0]);
buffer[0] &= 0x0f; /* Use condition. */
buffer[0] |= 0xe0;
/* Out of range conditional branch. Emit a branch around a 22bit jump. */
else if (fragP->fr_subtype == SUBYPTE_COND_9_22 + 1
|| fragP->fr_subtype == SUBYPTE_COND_9_22_32 + 1
- || fragP->fr_subtype == SUBYPTE_COND_9_17_22 + 2
+ || fragP->fr_subtype == SUBYPTE_COND_9_17_22 + 2
|| fragP->fr_subtype == SUBYPTE_COND_9_17_22_32 + 2)
{
unsigned char *buffer =
valueT
md_section_align (asection *seg, valueT addr)
{
- int align = bfd_get_section_alignment (stdoutput, seg);
- return ((addr + (1 << align) - 1) & (-1 << align));
+ int align = bfd_section_alignment (seg);
+ return ((addr + (1 << align) - 1) & -(1 << align));
}
void
md_begin (void)
{
- char *prev_name = "";
+ const char *prev_name = "";
const struct v850_opcode *op;
if (strncmp (TARGET_CPU, "v850e3v5", 8) == 0)
as_bad (_("Unable to determine default target processor from string: %s"),
TARGET_CPU);
+ if (soft_float == -1)
+ soft_float = machine < bfd_mach_v850e2v3;
+
v850_hash = hash_new ();
/* Insert unique names into hash table. The V850 instruction set
const unsigned char *opindex_ptr;
int next_opindex;
int relaxable = 0;
- unsigned long insn;
+ unsigned long insn = 0;
unsigned long insn_size;
char *f = NULL;
int i;
else if ((operand->flags & V850_OPERAND_EP) != 0)
{
char *start = input_line_pointer;
- char c = get_symbol_end ();
+ char *name;
+ char c = get_symbol_name (&name);
- if (strcmp (start, "ep") != 0 && strcmp (start, "r30") != 0)
+ if (strcmp (name, "ep") != 0 && strcmp (name, "r30") != 0)
{
/* Put things back the way we found them. */
- *input_line_pointer = c;
+ (void) restore_line_pointer (c);
input_line_pointer = start;
errmsg = _("expected EP register");
goto error;
}
- *input_line_pointer = c;
+ (void) restore_line_pointer (c);
str = input_line_pointer;
input_line_pointer = hold;
else if ((operand->flags & V850_OPERAND_CACHEOP) != 0)
{
if (!cacheop_name (&ex, TRUE))
- errmsg = _("invalid cache oparation name");
+ errmsg = _("invalid cache operation name");
}
else if ((operand->flags & V850_OPERAND_PREFOP) != 0)
{
if (!prefop_name (&ex, TRUE))
- errmsg = _("invalid pref oparation name");
+ errmsg = _("invalid pref operation name");
}
else if ((operand->flags & V850_OPERAND_VREG) != 0)
{
else if ((register_name (&ex)
&& (operand->flags & V850_OPERAND_REG) == 0))
{
+ char *name;
char c;
int exists = 0;
input_line_pointer = str;
- c = get_symbol_end ();
+ c = get_symbol_name (&name);
- if (symbol_find (str) != NULL)
+ if (symbol_find (name) != NULL)
exists = 1;
- *input_line_pointer = c;
+ (void) restore_line_pointer (c);
input_line_pointer = str;
expression (&ex);
dwarf2_emit_insn (0);
/* Write out the instruction. */
-
if (relaxable && fc > 0)
{
insn_size = 2;
{
arelent *reloc;
- reloc = xmalloc (sizeof (arelent));
- reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+ reloc = XNEW (arelent);
+ reloc->sym_ptr_ptr = XNEW (asymbol *);
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
else
insn = bfd_getl16 ((unsigned char *) where);
- /* When inserting loop offets a backwards displacement
+ /* When inserting loop offsets a backwards displacement
is encoded as a positive value. */
if (operand->flags & V850_INVERSE_PCREL)
value = - value;
return generic_force_reloc (fixP);
}
+
+/* Create a v850 note section. */
+void
+v850_md_end (void)
+{
+ segT note_sec;
+ segT orig_seg = now_seg;
+ subsegT orig_subseg = now_subseg;
+ enum v850_notes id;
+
+ note_sec = subseg_new (V850_NOTE_SECNAME, 0);
+ bfd_set_section_flags (note_sec, SEC_HAS_CONTENTS | SEC_READONLY | SEC_MERGE);
+ bfd_set_section_alignment (note_sec, 2);
+
+ /* Provide default values for all of the notes. */
+ for (id = V850_NOTE_ALIGNMENT; id <= NUM_V850_NOTES; id++)
+ {
+ int val = 0;
+ char * p;
+
+ /* Follow the standard note section layout:
+ First write the length of the name string. */
+ p = frag_more (4);
+ md_number_to_chars (p, 4, 4);
+
+ /* Next comes the length of the "descriptor", i.e., the actual data. */
+ p = frag_more (4);
+ md_number_to_chars (p, 4, 4);
+
+ /* Write the note type. */
+ p = frag_more (4);
+ md_number_to_chars (p, (valueT) id, 4);
+
+ /* Write the name field. */
+ p = frag_more (4);
+ memcpy (p, V850_NOTE_NAME, 4);
+
+ /* Finally, write the descriptor. */
+ p = frag_more (4);
+ switch (id)
+ {
+ case V850_NOTE_ALIGNMENT:
+ val = v850_data_8 ? EF_RH850_DATA_ALIGN8 : EF_RH850_DATA_ALIGN4;
+ break;
+
+ case V850_NOTE_DATA_SIZE:
+ /* GCC does not currently support an option
+ for 32-bit doubles with the V850 backend. */
+ val = EF_RH850_DOUBLE64;
+ break;
+
+ case V850_NOTE_FPU_INFO:
+ if (! soft_float)
+ switch (machine)
+ {
+ case bfd_mach_v850e3v5: val = EF_RH850_FPU30; break;
+ case bfd_mach_v850e2v3: val = EF_RH850_FPU20; break;
+ default: break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ md_number_to_chars (p, val, 4);
+ }
+
+ /* Paranoia - we probably do not need this. */
+ subseg_set (orig_seg, orig_subseg);
+}