/* tc-v850.c -- Assembler code for the NEC V850
- Copyright 1996-2013 Free Software Foundation, Inc.
+ Copyright (C) 1996-2015 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
/* Sign-extend a 16-bit number. */
#define SEXT16(x) ((((x) & 0xffff) ^ (~0x7fff)) + 0x8000)
-/* Temporarily holds the reloc in a cons expression. */
-static bfd_reloc_code_real_type hold_cons_reloc = BFD_RELOC_UNUSED;
-
/* Set to TRUE if we want to be pedantic about signed overflows. */
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;
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
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;
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
static bfd_reloc_code_real_type
handle_ctoff (const struct v850_operand *operand, const char **errmsg)
{
+ if (v850_target_arch == bfd_arch_v850_rh850)
+ {
+ *errmsg = _("ctoff() is not supported by the rh850 ABI. Use -mgcc-abi instead");
+ return BFD_RELOC_64; /* Used to indicate an error condition. */
+ }
+
if (operand == NULL)
return BFD_RELOC_V850_CALLT_16_16_OFFSET;
if (paren_skipped)
--input_line_pointer;
- return BFD_RELOC_UNUSED;
+ return BFD_RELOC_NONE;
}
/* Insert an operand value into an instruction. */
input_line_pointer = str;
/* lo(), hi(), hi0(), etc... */
- if ((reloc = v850_reloc_prefix (operand, &errmsg)) != BFD_RELOC_UNUSED)
+ if ((reloc = v850_reloc_prefix (operand, &errmsg)) != BFD_RELOC_NONE)
{
/* This is a fake reloc, used to indicate an error condition. */
if (reloc == BFD_RELOC_64)
fixups[fc].exp = ex;
fixups[fc].opindex = *opindex_ptr;
- fixups[fc].reloc = BFD_RELOC_UNUSED;
+ fixups[fc].reloc = BFD_RELOC_NONE;
++fc;
break;
}
reloc = fixups[i].reloc;
- if (reloc != BFD_RELOC_UNUSED)
+ if (reloc != BFD_RELOC_NONE)
{
reloc_howto_type *reloc_howto =
bfd_reloc_type_lookup (stdoutput, reloc);
else
insn = bfd_getl16 ((unsigned char *) where);
+ /* When inserting loop offets a backwards displacement
+ is encoded as a positive value. */
+ if (operand->flags & V850_INVERSE_PCREL)
+ value = - value;
+
insn = v850_insert_operand (insn, operand, (offsetT) value,
&errmsg);
if (errmsg)
/* Parse a cons expression. We have to handle hi(), lo(), etc
on the v850. */
-void
+bfd_reloc_code_real_type
parse_cons_expression_v850 (expressionS *exp)
{
const char *errmsg;
+ bfd_reloc_code_real_type r;
+
/* See if there's a reloc prefix like hi() we have to handle. */
- hold_cons_reloc = v850_reloc_prefix (NULL, &errmsg);
+ r = v850_reloc_prefix (NULL, &errmsg);
/* Do normal expression parsing. */
expression (exp);
+ return r;
}
/* Create a fixup for a cons expression. If parse_cons_expression_v850
cons_fix_new_v850 (fragS *frag,
int where,
int size,
- expressionS *exp)
+ expressionS *exp,
+ bfd_reloc_code_real_type r)
{
- if (hold_cons_reloc == BFD_RELOC_UNUSED)
+ if (r == BFD_RELOC_NONE)
{
if (size == 4)
- hold_cons_reloc = BFD_RELOC_32;
+ r = BFD_RELOC_32;
if (size == 2)
- hold_cons_reloc = BFD_RELOC_16;
+ r = BFD_RELOC_16;
if (size == 1)
- hold_cons_reloc = BFD_RELOC_8;
+ r = BFD_RELOC_8;
}
if (exp != NULL)
- fix_new_exp (frag, where, size, exp, 0, hold_cons_reloc);
+ fix_new_exp (frag, where, size, exp, 0, r);
else
- fix_new (frag, where, size, NULL, 0, 0, hold_cons_reloc);
-
- hold_cons_reloc = BFD_RELOC_UNUSED;
+ fix_new (frag, where, size, NULL, 0, 0, r);
}
bfd_boolean
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 (stdoutput, note_sec, SEC_HAS_CONTENTS | SEC_READONLY | SEC_MERGE);
+ bfd_set_section_alignment (stdoutput, 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);
+}