X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-arc.c;h=ed1e3fb5dd5c9504c66e1f377f3d85a4f322a33b;hb=030a2e78acf66c5c12e073ec3887a167da7a7195;hp=cd90fdf56d4e6817d1e6e6e6ac54809cbb0d906f;hpb=219d1afa89d0d53ca93a684cac341f16470f3ca0;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-arc.c b/gas/config/tc-arc.c index cd90fdf56d..ed1e3fb5dd 100644 --- a/gas/config/tc-arc.c +++ b/gas/config/tc-arc.c @@ -1,5 +1,5 @@ /* tc-arc.c -- Assembler for the ARC - Copyright (C) 1994-2018 Free Software Foundation, Inc. + Copyright (C) 1994-2020 Free Software Foundation, Inc. Contributor: Claudiu Zissulescu @@ -22,7 +22,6 @@ #include "as.h" #include "subsegs.h" -#include "struc-symbol.h" #include "dwarf2dbg.h" #include "dw2gencfi.h" #include "safe-ctype.h" @@ -49,9 +48,6 @@ #define LP_INSN(x) ((MAJOR_OPCODE (x) == 0x4) \ && (SUB_OPCODE (x) == 0x28)) -/* Equal to MAX_PRECISION in atof-ieee.c. */ -#define MAX_LITTLENUMS 6 - #ifndef TARGET_WITH_CPU #define TARGET_WITH_CPU "arc700" #endif /* TARGET_WITH_CPU */ @@ -475,6 +471,9 @@ static const struct cpu_type /* Information about the cpu/variant we're assembling for. */ static struct cpu_type selected_cpu = { 0, 0, 0, E_ARC_OSABI_CURRENT, 0 }; +/* TRUE if current assembly code uses RF16 only registers. */ +static bfd_boolean rf16_only = TRUE; + /* MPY option. */ static unsigned mpy_option = 0; @@ -796,7 +795,7 @@ md_number_to_chars_midend (char *buf, unsigned long long val, int n) md_number_to_chars (buf, val, n); break; case 6: - md_number_to_chars (buf, (val & 0xffff00000000) >> 32, 2); + md_number_to_chars (buf, (val & 0xffff00000000ull) >> 32, 2); md_number_to_chars_midend (buf + 2, (val & 0xffffffff), 4); break; case 4: @@ -804,7 +803,7 @@ md_number_to_chars_midend (char *buf, unsigned long long val, int n) md_number_to_chars (buf + 2, (val & 0xffff), 2); break; case 8: - md_number_to_chars_midend (buf, (val & 0xffffffff00000000) >> 32, 4); + md_number_to_chars_midend (buf, (val & 0xffffffff00000000ull) >> 32, 4); md_number_to_chars_midend (buf + 4, (val & 0xffffffff), 4); break; default: @@ -1093,6 +1092,102 @@ debug_exp (expressionS *t) fflush (stderr); } +/* Helper for parsing an argument, used for sorting out the relocation + type. */ + +static void +parse_reloc_symbol (expressionS *resultP) +{ + char *reloc_name, c, *sym_name; + size_t len; + int i; + const struct arc_reloc_op_tag *r; + expressionS right; + symbolS *base; + + /* A relocation operand has the following form + @identifier@relocation_type. The identifier is already in + tok! */ + if (resultP->X_op != O_symbol) + { + as_bad (_("No valid label relocation operand")); + resultP->X_op = O_illegal; + return; + } + + /* Parse @relocation_type. */ + input_line_pointer++; + c = get_symbol_name (&reloc_name); + len = input_line_pointer - reloc_name; + if (len == 0) + { + as_bad (_("No relocation operand")); + resultP->X_op = O_illegal; + return; + } + + /* Go through known relocation and try to find a match. */ + r = &arc_reloc_op[0]; + for (i = arc_num_reloc_op - 1; i >= 0; i--, r++) + if (len == r->length + && memcmp (reloc_name, r->name, len) == 0) + break; + if (i < 0) + { + as_bad (_("Unknown relocation operand: @%s"), reloc_name); + resultP->X_op = O_illegal; + return; + } + + *input_line_pointer = c; + SKIP_WHITESPACE_AFTER_NAME (); + /* Extra check for TLS: base. */ + if (*input_line_pointer == '@') + { + if (resultP->X_op_symbol != NULL + || resultP->X_op != O_symbol) + { + as_bad (_("Unable to parse TLS base: %s"), + input_line_pointer); + resultP->X_op = O_illegal; + return; + } + input_line_pointer++; + c = get_symbol_name (&sym_name); + base = symbol_find_or_make (sym_name); + resultP->X_op = O_subtract; + resultP->X_op_symbol = base; + restore_line_pointer (c); + right.X_add_number = 0; + } + + if ((*input_line_pointer != '+') + && (*input_line_pointer != '-')) + right.X_add_number = 0; + else + { + /* Parse the constant of a complex relocation expression + like @identifier@reloc +/- const. */ + if (! r->complex_expr) + { + as_bad (_("@%s is not a complex relocation."), r->name); + resultP->X_op = O_illegal; + return; + } + expression (&right); + if (right.X_op != O_constant) + { + as_bad (_("Bad expression: @%s + %s."), + r->name, input_line_pointer); + resultP->X_op = O_illegal; + return; + } + } + + resultP->X_md = r->op; + resultP->X_add_number = right.X_add_number; +} + /* Parse the arguments to an opcode. */ static int @@ -1105,11 +1200,6 @@ tokenize_arguments (char *str, bfd_boolean saw_arg = FALSE; int brk_lvl = 0; int num_args = 0; - int i; - size_t len; - const struct arc_reloc_op_tag *r; - expressionS tmpE; - char *reloc_name, c; memset (tok, 0, sizeof (*tok) * ntok); @@ -1171,95 +1261,21 @@ tokenize_arguments (char *str, goto err; /* Parse @label. */ + input_line_pointer++; tok->X_op = O_symbol; tok->X_md = O_absent; expression (tok); - if (*input_line_pointer != '@') - goto normalsymbol; /* This is not a relocation. */ - - relocationsym: - - /* A relocation operand has the following form - @identifier@relocation_type. The identifier is already - in tok! */ - if (tok->X_op != O_symbol) - { - as_bad (_("No valid label relocation operand")); - goto err; - } - /* Parse @relocation_type. */ - input_line_pointer++; - c = get_symbol_name (&reloc_name); - len = input_line_pointer - reloc_name; - if (len == 0) - { - as_bad (_("No relocation operand")); - goto err; - } - - /* Go through known relocation and try to find a match. */ - r = &arc_reloc_op[0]; - for (i = arc_num_reloc_op - 1; i >= 0; i--, r++) - if (len == r->length - && memcmp (reloc_name, r->name, len) == 0) - break; - if (i < 0) - { - as_bad (_("Unknown relocation operand: @%s"), reloc_name); - goto err; - } - - *input_line_pointer = c; - SKIP_WHITESPACE_AFTER_NAME (); - /* Extra check for TLS: base. */ if (*input_line_pointer == '@') - { - symbolS *base; - if (tok->X_op_symbol != NULL - || tok->X_op != O_symbol) - { - as_bad (_("Unable to parse TLS base: %s"), - input_line_pointer); - goto err; - } - input_line_pointer++; - char *sym_name; - c = get_symbol_name (&sym_name); - base = symbol_find_or_make (sym_name); - tok->X_op = O_subtract; - tok->X_op_symbol = base; - restore_line_pointer (c); - tmpE.X_add_number = 0; - } - if ((*input_line_pointer != '+') - && (*input_line_pointer != '-')) - { - tmpE.X_add_number = 0; - } - else - { - /* Parse the constant of a complex relocation expression - like @identifier@reloc +/- const. */ - if (! r->complex_expr) - { - as_bad (_("@%s is not a complex relocation."), r->name); - goto err; - } - expression (&tmpE); - if (tmpE.X_op != O_constant) - { - as_bad (_("Bad expression: @%s + %s."), - r->name, input_line_pointer); - goto err; - } - } - - tok->X_md = r->op; - tok->X_add_number = tmpE.X_add_number; + parse_reloc_symbol (tok); debug_exp (tok); + if (tok->X_op == O_illegal + || tok->X_op == O_absent + || num_args == ntok) + goto err; + saw_comma = FALSE; saw_arg = TRUE; tok++; @@ -1283,9 +1299,8 @@ tokenize_arguments (char *str, identifier@relocation_type, if it is the case parse the relocation type as well. */ if (*input_line_pointer == '@') - goto relocationsym; + parse_reloc_symbol (tok); - normalsymbol: debug_exp (tok); if (tok->X_op == O_illegal @@ -1882,13 +1897,20 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry, case O_symbol: { const char *p; + char *tmpp, *pp; const struct arc_aux_reg *auxr; if (opcode->insn_class != AUXREG) goto de_fault; p = S_GET_NAME (tok[tokidx].X_add_symbol); - auxr = hash_find (arc_aux_hash, p); + /* For compatibility reasons, an aux register can + be spelled with upper or lower case + letters. */ + tmpp = strdup (p); + for (pp = tmpp; *pp; ++pp) *pp = TOLOWER (*pp); + + auxr = hash_find (arc_aux_hash, tmpp); if (auxr) { /* We modify the token array here, safe in the @@ -1899,6 +1921,7 @@ find_opcode_match (const struct arc_opcode_hash_entry *entry, tok[tokidx].X_add_number = auxr->address; ARC_SET_FLAG (tok[tokidx].X_add_symbol, ARC_FLAG_AUX); } + free (tmpp); if (tok[tokidx].X_op != O_constant) goto de_fault; @@ -2375,6 +2398,17 @@ autodetect_attributes (const struct arc_opcode *opcode, default: break; } + + switch (tok[i].X_op) + { + case O_register: + if ((tok[i].X_add_number >= 4 && tok[i].X_add_number <= 9) + || (tok[i].X_add_number >= 16 && tok[i].X_add_number <= 25)) + rf16_only = FALSE; + break; + default: + break; + } } } @@ -2688,7 +2722,7 @@ valueT md_section_align (segT segment, valueT size) { - int align = bfd_get_section_alignment (stdoutput, segment); + int align = bfd_section_alignment (segment); return ((size + (1 << align) - 1) & (-((valueT) 1 << align))); } @@ -3250,7 +3284,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, int size, fix; struct arc_relax_type *relax_arg = &fragP->tc_frag_data; - fix = (fragP->fr_fix < 0 ? 0 : fragP->fr_fix); + fix = fragP->fr_fix; dest = fragP->fr_literal + fix; table_entry = TC_GENERIC_RELAX_TABLE + fragP->fr_subtype; @@ -3318,16 +3352,18 @@ md_atof (int type, char *litP, int *sizeP) /* Called for any expression that can not be recognized. When the function is called, `input_line_pointer' will point to the start of - the expression. */ + the expression. We use it when we have complex operations like + @label1 - @label2. */ void -md_operand (expressionS *expressionP ATTRIBUTE_UNUSED) +md_operand (expressionS *expressionP) { char *p = input_line_pointer; if (*p == '@') { input_line_pointer++; expressionP->X_op = O_symbol; + expressionP->X_md = O_absent; expression (expressionP); } } @@ -3346,7 +3382,8 @@ arc_parse_name (const char *name, if (!assembling_insn) return FALSE; - if (e->X_op == O_symbol) + if (e->X_op == O_symbol + && e->X_md == O_absent) return FALSE; sym = hash_find (arc_reg_hash, name); @@ -4189,7 +4226,7 @@ arc_check_reloc (expressionS *exp, if (*r_type_p == BFD_RELOC_32 && exp->X_op == O_subtract && exp->X_op_symbol != NULL - && exp->X_op_symbol->bsym->section == now_seg) + && S_GET_SEGMENT (exp->X_op_symbol) == now_seg) *r_type_p = BFD_RELOC_ARC_32_PCREL; } @@ -4369,6 +4406,10 @@ tokenize_extinsn (extInstruction_t *einsn) insn_name = xstrdup (p); restore_line_pointer (c); + /* Convert to lower case. */ + for (p = insn_name; *p; ++p) + *p = TOLOWER (*p); + /* 2nd: get major opcode. */ if (*input_line_pointer != ',') { @@ -4507,8 +4548,7 @@ arc_set_ext_seg (void) if (!arcext_section) { arcext_section = subseg_new (".arcextmap", 0); - bfd_set_section_flags (stdoutput, arcext_section, - SEC_READONLY | SEC_HAS_CONTENTS); + bfd_set_section_flags (arcext_section, SEC_READONLY | SEC_HAS_CONTENTS); } else subseg_set (arcext_section, 0); @@ -5002,6 +5042,20 @@ arc_set_public_attributes (void) /* Tag_ARC_ABI_tls. */ arc_set_attribute_int (Tag_ARC_ABI_tls, tls_option); + + /* Tag_ARC_ATR_version. */ + arc_set_attribute_int (Tag_ARC_ATR_version, 1); + + /* Tag_ARC_ABI_rf16. */ + if (attributes_set_explicitly[Tag_ARC_ABI_rf16] + && bfd_elf_get_obj_attr_int (stdoutput, OBJ_ATTR_PROC, + Tag_ARC_ABI_rf16) + && !rf16_only) + { + as_warn (_("Overwrite explicitly set Tag_ARC_ABI_rf16 to full " + "register file")); + bfd_elf_add_proc_attr_int (stdoutput, Tag_ARC_ABI_rf16, 0); + } } /* Add the default contents for the .ARC.attributes section. */ @@ -5046,7 +5100,8 @@ int arc_convert_symbolic_attribute (const char *name) T (Tag_ARC_ABI_double_size), T (Tag_ARC_ISA_config), T (Tag_ARC_ISA_apex), - T (Tag_ARC_ISA_mpy_option) + T (Tag_ARC_ISA_mpy_option), + T (Tag_ARC_ATR_version) #undef T }; unsigned int i;