X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-v850.c;h=dfb43cbc16f3ee4ae4177eddd8fbed0fb8ccda2e;hb=ff8577f64987a898e1dc5eb6afb66a404fb7bb16;hp=d7bd99a6435cf234d4768774ff21dffcb3d54638;hpb=4b95cf5c0c75d6efc1b2f96af72317aecca079f1;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-v850.c b/gas/config/tc-v850.c index d7bd99a643..dfb43cbc16 100644 --- a/gas/config/tc-v850.c +++ b/gas/config/tc-v850.c @@ -1,5 +1,5 @@ /* tc-v850.c -- Assembler code for the NEC V850 - Copyright (C) 1996-2014 Free Software Foundation, Inc. + Copyright (C) 1996-2019 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -27,19 +27,19 @@ /* 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; -/* 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; @@ -229,7 +229,7 @@ do_v850_seg (int i, subsegT sub) 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; } @@ -270,8 +270,7 @@ v850_comm (int area) 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; @@ -936,7 +935,7 @@ static const struct reg_name vector_registers[] = (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 @@ -1005,15 +1004,14 @@ register_name (expressionS *expressionP) 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; @@ -1057,14 +1055,13 @@ system_register_name (expressionS *expressionP, 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) @@ -1118,13 +1115,12 @@ cc_name (expressionS *expressionP, 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) @@ -1169,13 +1165,12 @@ float_cc_name (expressionS *expressionP, 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) @@ -1220,13 +1215,12 @@ cacheop_name (expressionS * expressionP, 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) @@ -1269,13 +1263,12 @@ prefop_name (expressionS * expressionP, 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) @@ -1317,15 +1310,14 @@ vector_register_name (expressionS *expressionP) 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; @@ -1374,13 +1366,13 @@ skip_white_space (void) { 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) { @@ -1405,7 +1397,7 @@ parse_register_list (unsigned long *insn, 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 != '{') { @@ -1540,6 +1532,8 @@ struct option md_longopts[] = size_t md_longopts_size = sizeof (md_longopts); +static bfd_boolean v850_data_8 = FALSE; + void md_show_usage (FILE *stream) { @@ -1563,10 +1557,12 @@ 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') { @@ -1649,9 +1645,19 @@ md_parse_option (int c, char *arg) 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; @@ -1664,7 +1670,7 @@ md_undefined_symbol (char *name ATTRIBUTE_UNUSED) return 0; } -char * +const char * md_atof (int type, char *litp, int *sizep) { return ieee_md_atof (type, litp, sizep, FALSE); @@ -1753,7 +1759,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, /* 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 = @@ -1872,14 +1878,14 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, 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) @@ -1943,6 +1949,9 @@ md_begin (void) 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 @@ -2032,6 +2041,12 @@ handle_lo16 (const struct v850_operand *operand, const char **errmsg) 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; @@ -2156,7 +2171,7 @@ v850_reloc_prefix (const struct v850_operand *operand, const char **errmsg) if (paren_skipped) --input_line_pointer; - return BFD_RELOC_UNUSED; + return BFD_RELOC_NONE; } /* Insert an operand value into an instruction. */ @@ -2283,7 +2298,7 @@ md_assemble (char *str) 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; @@ -2407,7 +2422,7 @@ md_assemble (char *str) 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) @@ -2769,18 +2784,19 @@ md_assemble (char *str) 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; @@ -2812,12 +2828,12 @@ md_assemble (char *str) 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) { @@ -2827,6 +2843,7 @@ md_assemble (char *str) else if ((register_name (&ex) && (operand->flags & V850_OPERAND_REG) == 0)) { + char *name; char c; int exists = 0; @@ -2839,12 +2856,12 @@ md_assemble (char *str) 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); @@ -2977,7 +2994,7 @@ md_assemble (char *str) fixups[fc].exp = ex; fixups[fc].opindex = *opindex_ptr; - fixups[fc].reloc = BFD_RELOC_UNUSED; + fixups[fc].reloc = BFD_RELOC_NONE; ++fc; break; } @@ -3048,7 +3065,6 @@ md_assemble (char *str) dwarf2_emit_insn (0); /* Write out the instruction. */ - if (relaxable && fc > 0) { insn_size = 2; @@ -3239,7 +3255,7 @@ md_assemble (char *str) 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); @@ -3320,8 +3336,8 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) { 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; @@ -3459,7 +3475,7 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED) 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; @@ -3634,15 +3650,18 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED) /* 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 @@ -3653,24 +3672,23 @@ void 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 @@ -3711,3 +3729,73 @@ v850_force_relocation (struct fix *fixP) 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); +}