X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-ppc.c;h=fc2a0458288d5228ad0598cd3e6ae7b8e1826293;hb=024425668d120663a73913352df701c8f0aea316;hp=5cfe1db19a4208206471a50a1b069052f8af28c6;hpb=62ebcb5cbedf0fdc0b5faaa05e46aa43ced2aa68;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 5cfe1db19a..fc2a045828 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -1,5 +1,5 @@ /* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000) - Copyright (C) 1994-2014 Free Software Foundation, Inc. + Copyright (C) 1994-2016 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. This file is part of GAS, the GNU Assembler. @@ -206,11 +206,19 @@ ppc_cpu_t sticky = 0; /* Value for ELF e_flags EF_PPC64_ABI. */ unsigned int ppc_abiversion = 0; +#ifdef OBJ_ELF /* Flags set on encountering toc relocs. */ -enum { +static enum { has_large_toc_reloc = 1, has_small_toc_reloc = 2 } toc_reloc_types; +#endif + +/* Warn on emitting data to code sections. */ +int warn_476; +unsigned long last_insn; +segT last_seg; +subsegT last_subseg; /* The target specific pseudo-ops which we support. */ @@ -296,7 +304,7 @@ const pseudo_typeS md_pseudo_table[] = /* Structure to hold information about predefined registers. */ struct pd_reg { - char *name; + const char *name; int value; }; @@ -854,7 +862,7 @@ register_name (expressionS *expressionP) else if (!reg_names_p || !ISALPHA (name[0])) return FALSE; - c = get_symbol_end (); + c = get_symbol_name (&name); reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name); /* Put back the delimiting char. */ @@ -1040,18 +1048,6 @@ static segT ppc_current_section; #ifdef OBJ_ELF symbolS *GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE" */ -#define PPC_APUINFO_ISEL 0x40 -#define PPC_APUINFO_PMR 0x41 -#define PPC_APUINFO_RFMCI 0x42 -#define PPC_APUINFO_CACHELCK 0x43 -#define PPC_APUINFO_SPE 0x100 -#define PPC_APUINFO_EFS 0x101 -#define PPC_APUINFO_BRLOCK 0x102 -#define PPC_APUINFO_VLE 0x104 - -/* - * We keep a list of APUinfo - */ unsigned long *ppc_apuinfo_list; unsigned int ppc_apuinfo_num; unsigned int ppc_apuinfo_num_alloc; @@ -1065,12 +1061,14 @@ const char *const md_shortopts = "um:"; #define OPTION_NOPS (OPTION_MD_BASE + 0) const struct option md_longopts[] = { {"nops", required_argument, NULL, OPTION_NOPS}, + {"ppc476-workaround", no_argument, &warn_476, 1}, + {"no-ppc476-workaround", no_argument, &warn_476, 0}, {NULL, no_argument, NULL, 0} }; const size_t md_longopts_size = sizeof (md_longopts); int -md_parse_option (int c, char *arg) +md_parse_option (int c, const char *arg) { ppc_cpu_t new_cpu; @@ -1243,6 +1241,9 @@ md_parse_option (int c, char *arg) } break; + case 0: + break; + default: return 0; } @@ -1270,7 +1271,8 @@ PowerPC options:\n\ -m476 generate code for PowerPC 476\n\ -m7400, -m7410, -m7450, -m7455\n\ generate code for PowerPC 7400/7410/7450/7455\n\ --m750cl generate code for PowerPC 750cl\n")); +-m750cl generate code for PowerPC 750cl\n\ +-m821, -m850, -m860 generate code for PowerPC 821/850/860\n")); fprintf (stream, _("\ -mppc64, -m620 generate code for PowerPC 620/625/630\n\ -mppc64bridge generate code for PowerPC 64, including bridge insns\n\ @@ -1282,6 +1284,7 @@ PowerPC options:\n\ -mpower6, -mpwr6 generate code for Power6 architecture\n\ -mpower7, -mpwr7 generate code for Power7 architecture\n\ -mpower8, -mpwr8 generate code for Power8 architecture\n\ +-mpower9, -mpwr9 generate code for Power9 architecture\n\ -mcell generate code for Cell Broadband Engine architecture\n\ -mcom generate code Power/PowerPC common instructions\n\ -many generate code for any architecture (PWR/PWRX/PPC)\n")); @@ -1316,7 +1319,8 @@ PowerPC options:\n\ -Qy, -Qn ignored\n")); #endif fprintf (stream, _("\ --nops=count when aligning, more than COUNT nops uses a branch\n")); +-nops=count when aligning, more than COUNT nops uses a branch\n\ +-ppc476-workaround warn if emitting data to code sections\n")); } /* Set ppc_cpu if it is not already set. */ @@ -1388,7 +1392,7 @@ ppc_mach (void) return bfd_mach_ppc; } -extern char* +extern const char* ppc_target_format (void) { #ifdef OBJ_COFF @@ -1444,7 +1448,7 @@ insn_validate (const struct powerpc_opcode *op) else { const struct powerpc_operand *operand = &powerpc_operands[*o]; - if (operand->shift != PPC_OPSHIFT_INV) + if (operand->shift != (int) PPC_OPSHIFT_INV) { unsigned long mask; @@ -1547,6 +1551,18 @@ ppc_setup_opcodes (void) bad_insn = TRUE; } } + if ((op->flags & PPC_OPCODE_VLE) != 0) + { + as_bad (_("%s is enabled by vle flag"), op->name); + bad_insn = TRUE; + } + if (PPC_OP (op->opcode) != 4 + && PPC_OP (op->opcode) != 31 + && (op->deprecated & PPC_OPCODE_VLE) == 0) + { + as_bad (_("%s not disabled by vle flag"), op->name); + bad_insn = TRUE; + } bad_insn |= insn_validate (op); } @@ -1618,10 +1634,6 @@ ppc_setup_opcodes (void) } } - if ((ppc_cpu & PPC_OPCODE_VLE) != 0) - for (op = vle_opcodes; op < op_end; op++) - hash_insert (ppc_hash, op->name, (void *) op); - /* Insert the macros into a hash table. */ ppc_macro_hash = hash_new (); @@ -1720,7 +1732,7 @@ ppc_cleanup (void) unsigned int i; /* Create the .PPC.EMB.apuinfo section. */ - apuinfo_secp = subseg_new (".PPC.EMB.apuinfo", 0); + apuinfo_secp = subseg_new (APUINFO_SECTION_NAME, 0); bfd_set_section_flags (stdoutput, apuinfo_secp, SEC_HAS_CONTENTS | SEC_READONLY); @@ -1735,7 +1747,7 @@ ppc_cleanup (void) md_number_to_chars (p, (valueT) 2, 4); p = frag_more (8); - strcpy (p, "APUinfo"); + strcpy (p, APUINFO_LABEL); for (i = 0; i < ppc_apuinfo_num; i++) { @@ -1760,7 +1772,7 @@ ppc_insert_operand (unsigned long insn, const struct powerpc_operand *operand, offsetT val, ppc_cpu_t cpu, - char *file, + const char *file, unsigned int line) { long min, max, right; @@ -1769,10 +1781,21 @@ ppc_insert_operand (unsigned long insn, right = max & -max; min = 0; - if ((operand->flags & PPC_OPERAND_SIGNED) != 0) + if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0) + { + /* Extend the allowed range for addis to [-32768, 65535]. + Similarly for cmpli and some VLE high part insns. For 64-bit + it would be good to disable this for signed fields since the + value is sign extended into the high 32 bits of the register. + If the value is, say, an address, then we might care about + the high bits. However, gcc as of 2014-06 uses unsigned + values when loading the high part of 64-bit constants using + lis. */ + min = ~(max >> 1) & -right; + } + else if ((operand->flags & PPC_OPERAND_SIGNED) != 0) { - if ((operand->flags & PPC_OPERAND_SIGNOPT) == 0) - max = (max >> 1) & -right; + max = (max >> 1) & -right; min = ~max & -right; } @@ -1837,7 +1860,7 @@ static bfd_reloc_code_real_type ppc_elf_suffix (char **str_p, expressionS *exp_p) { struct map_bfd { - char *string; + const char *string; unsigned int length : 8; unsigned int valid32 : 1; unsigned int valid64 : 1; @@ -2056,6 +2079,37 @@ ppc_elf_parse_cons (expressionS *exp, unsigned int nbytes) return BFD_RELOC_NONE; } +/* Warn when emitting data to code sections, unless we are emitting + a relocation that ld --ppc476-workaround uses to recognise data + *and* there was an unconditional branch prior to the data. */ + +void +ppc_elf_cons_fix_check (expressionS *exp ATTRIBUTE_UNUSED, + unsigned int nbytes, fixS *fix) +{ + if (warn_476 + && (now_seg->flags & SEC_CODE) != 0 + && (nbytes != 4 + || fix == NULL + || !(fix->fx_r_type == BFD_RELOC_32 + || fix->fx_r_type == BFD_RELOC_CTOR + || fix->fx_r_type == BFD_RELOC_32_PCREL) + || !(last_seg == now_seg && last_subseg == now_subseg) + || !((last_insn & (0x3f << 26)) == (18u << 26) + || ((last_insn & (0x3f << 26)) == (16u << 26) + && (last_insn & (0x14 << 21)) == (0x14 << 21)) + || ((last_insn & (0x3f << 26)) == (19u << 26) + && (last_insn & (0x3ff << 1)) == (16u << 1) + && (last_insn & (0x14 << 21)) == (0x14 << 21))))) + { + /* Flag that we've warned. */ + if (fix != NULL) + fix->fx_tcbit = 1; + + as_warn (_("data in executable section")); + } +} + /* Solaris pseduo op to change to the .rodata section. */ static void ppc_elf_rdata (int xxx) @@ -2085,13 +2139,12 @@ ppc_elf_lcomm (int xxx ATTRIBUTE_UNUSED) char *pfrag; int align2; - name = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (&name); - /* just after name is now '\0'. */ + /* Just after name is now '\0'. */ p = input_line_pointer; *p = c; - SKIP_WHITESPACE (); + SKIP_WHITESPACE_AFTER_NAME (); if (*input_line_pointer != ',') { as_bad (_("expected comma after symbol-name: rest of line ignored.")); @@ -2181,8 +2234,8 @@ ppc_elf_lcomm (int xxx ATTRIBUTE_UNUSED) static void ppc_elf_localentry (int ignore ATTRIBUTE_UNUSED) { - char *name = input_line_pointer; - char c = get_symbol_end (); + char *name; + char c = get_symbol_name (&name); char *p; expressionS exp; symbolS *sym; @@ -2191,7 +2244,7 @@ ppc_elf_localentry (int ignore ATTRIBUTE_UNUSED) p = input_line_pointer; *p = c; - SKIP_WHITESPACE (); + SKIP_WHITESPACE_AFTER_NAME (); if (*input_line_pointer != ',') { *p = 0; @@ -2333,7 +2386,6 @@ ppc_frob_file_before_adjust (void) const char *name; char *dotname; symbolS *dotsym; - size_t len; name = S_GET_NAME (symp); if (name[0] == '.') @@ -2343,10 +2395,7 @@ ppc_frob_file_before_adjust (void) || S_IS_DEFINED (symp)) continue; - len = strlen (name) + 1; - dotname = xmalloc (len + 1); - dotname[0] = '.'; - memcpy (dotname + 1, name, len); + dotname = concat (".", name, (char *) NULL); dotsym = symbol_find_noref (dotname, 1); free (dotname); if (dotsym != NULL && (symbol_used_p (dotsym) @@ -2434,8 +2483,7 @@ parse_toc_entry (enum toc_size_qualifier *toc_kind) SKIP_WHITESPACE (); /* Find the spelling of the operand. */ - toc_spec = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (&toc_spec); if (strcmp (toc_spec, "toc") == 0) { @@ -2464,7 +2512,7 @@ parse_toc_entry (enum toc_size_qualifier *toc_kind) /* Now find the ']'. */ *input_line_pointer = c; - SKIP_WHITESPACE (); /* leading whitespace could be there. */ + SKIP_WHITESPACE_AFTER_NAME (); /* leading whitespace could be there. */ c = *input_line_pointer++; /* input_line_pointer->past char in c. */ if (c != ']') @@ -2517,14 +2565,13 @@ ppc_apuinfo_section_add (unsigned int apu, unsigned int version) if (ppc_apuinfo_num_alloc == 0) { ppc_apuinfo_num_alloc = 4; - ppc_apuinfo_list = (unsigned long *) - xmalloc (sizeof (unsigned long) * ppc_apuinfo_num_alloc); + ppc_apuinfo_list = XNEWVEC (unsigned long, ppc_apuinfo_num_alloc); } else { ppc_apuinfo_num_alloc += 4; - ppc_apuinfo_list = (unsigned long *) xrealloc (ppc_apuinfo_list, - sizeof (unsigned long) * ppc_apuinfo_num_alloc); + ppc_apuinfo_list = XRESIZEVEC (unsigned long, ppc_apuinfo_list, + ppc_apuinfo_num_alloc); } } ppc_apuinfo_list[ppc_apuinfo_num++] = APUID (apu, version); @@ -2696,12 +2743,18 @@ md_assemble (char *str) if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 && skip_optional) { + long val = ppc_optional_operand_value (operand); if (operand->insert) { - insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg); + insn = (*operand->insert) (insn, val, ppc_cpu, &errmsg); if (errmsg != (const char *) NULL) as_bad ("%s", errmsg); } + else if (operand->shift >= 0) + insn |= ((long) val & operand->bitm) << operand->shift; + else + insn |= ((long) val & operand->bitm) >> -operand->shift; + if ((operand->flags & PPC_OPERAND_NEXT) != 0) next_opindex = *opindex_ptr + 1; continue; @@ -3024,11 +3077,16 @@ md_assemble (char *str) break; } + /* addpcis. */ + if (opcode->opcode == (19 << 26) + (2 << 1) + && reloc == BFD_RELOC_HI16_S) + reloc = BFD_RELOC_PPC_REL16DX_HA; + /* If VLE-mode convert LO/HI/HA relocations. */ if (opcode->flags & PPC_OPCODE_VLE) { int tmp_insn = insn & opcode->mask; - + int use_d_reloc = (tmp_insn == E_OR2I_INSN || tmp_insn == E_AND2I_DOT_INSN || tmp_insn == E_OR2IS_INSN @@ -3066,7 +3124,7 @@ md_assemble (char *str) else if (use_a_reloc) reloc = BFD_RELOC_PPC_VLE_HI16A; break; - + case BFD_RELOC_HI16_S: if (use_d_reloc) reloc = BFD_RELOC_PPC_VLE_HA16D; @@ -3313,7 +3371,12 @@ md_assemble (char *str) ppc_apuinfo_section_add (PPC_APUINFO_CACHELCK, 1); if (opcode->flags & PPC_OPCODE_RFMCI) ppc_apuinfo_section_add (PPC_APUINFO_RFMCI, 1); - if (opcode->flags & PPC_OPCODE_VLE) + /* Only set the VLE flag if the instruction has been pulled via + the VLE instruction set. This way the flag is guaranteed to + be set for VLE-only instructions or for VLE-only processors, + however it'll remain clear for dual-mode instructions on + dual-mode and, more importantly, standard-mode processors. */ + if ((ppc_cpu & opcode->flags) == PPC_OPCODE_VLE) ppc_apuinfo_section_add (PPC_APUINFO_VLE, 1); } #endif @@ -3345,6 +3408,9 @@ md_assemble (char *str) frag_now->insn_addr = addr_mod; frag_now->has_code = 1; md_number_to_chars (f, insn, insn_length); + last_insn = insn; + last_seg = now_seg; + last_subseg = now_subseg; #ifdef OBJ_ELF dwarf2_emit_insn (insn_length); @@ -3367,9 +3433,6 @@ md_assemble (char *str) size = bfd_get_reloc_size (reloc_howto); offset = target_big_endian ? (insn_length - size) : 0; - if (size < 1 || size > 4) - abort (); - fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size, @@ -3451,7 +3514,7 @@ ppc_macro (char *str, const struct powerpc_macro *macro) } /* Put the string together. */ - complete = s = (char *) alloca (len + 1); + complete = s = XNEWVEC (char, len + 1); format = macro->format; while (*format != '\0') { @@ -3469,6 +3532,7 @@ ppc_macro (char *str, const struct powerpc_macro *macro) /* Assemble the constructed instruction. */ md_assemble (complete); + free (complete); } #ifdef OBJ_ELF @@ -3502,6 +3566,8 @@ ppc_section_flags (flagword flags, bfd_vma attr ATTRIBUTE_UNUSED, int type) static void ppc_byte (int ignore ATTRIBUTE_UNUSED) { + int count = 0; + if (*input_line_pointer != '\"') { cons (1); @@ -3525,8 +3591,11 @@ ppc_byte (int ignore ATTRIBUTE_UNUSED) } FRAG_APPEND_1_CHAR (c); + ++count; } + if (warn_476 && count != 0 && (now_seg->flags & SEC_CODE) != 0) + as_warn (_("data in executable section")); demand_empty_rest_of_line (); } @@ -3557,10 +3626,9 @@ ppc_comm (int lcomm) symbolS *sym; char *pfrag; - name = input_line_pointer; - endc = get_symbol_end (); + endc = get_symbol_name (&name); end_name = input_line_pointer; - *end_name = endc; + (void) restore_line_pointer (endc); if (*input_line_pointer != ',') { @@ -3611,12 +3679,11 @@ ppc_comm (int lcomm) } ++input_line_pointer; - lcomm_name = input_line_pointer; - lcomm_endc = get_symbol_end (); + lcomm_endc = get_symbol_name (&lcomm_name); lcomm_sym = symbol_find_or_make (lcomm_name); - *input_line_pointer = lcomm_endc; + (void) restore_line_pointer (lcomm_endc); /* The fourth argument to .lcomm is the alignment. */ if (*input_line_pointer != ',') @@ -3719,12 +3786,11 @@ ppc_csect (int ignore ATTRIBUTE_UNUSED) symbolS *sym; offsetT align; - name = input_line_pointer; - endc = get_symbol_end (); + endc = get_symbol_name (&name); sym = symbol_find_or_make (name); - *input_line_pointer = endc; + (void) restore_line_pointer (endc); if (S_GET_NAME (sym)[0] == '\0') { @@ -3892,15 +3958,14 @@ ppc_dwsect (int ignore ATTRIBUTE_UNUSED) /* Parse opt-label. */ if (*input_line_pointer == ',') { - const char *label; + char *label; char c; ++input_line_pointer; - label = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (&label); opt_label = symbol_find_or_make (label); - *input_line_pointer = c; + (void) restore_line_pointer (c); } else opt_label = NULL; @@ -3940,8 +4005,7 @@ ppc_dwsect (int ignore ATTRIBUTE_UNUSED) else { /* Create a new dw subsection. */ - subseg = (struct dw_subsection *) - xmalloc (sizeof (struct dw_subsection)); + subseg = XNEW (struct dw_subsection); if (opt_label == NULL) { @@ -4030,8 +4094,7 @@ ppc_named_section (int ignore ATTRIBUTE_UNUSED) char c; symbolS *sym; - user_name = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (&user_name); if (strcmp (user_name, ".text") == 0) real_name = ".text[PR]"; @@ -4040,12 +4103,12 @@ ppc_named_section (int ignore ATTRIBUTE_UNUSED) else { as_bad (_("the XCOFF file format does not support arbitrary sections")); - *input_line_pointer = c; + (void) restore_line_pointer (c); ignore_rest_of_line (); return; } - *input_line_pointer = c; + (void) restore_line_pointer (c); sym = symbol_find_or_make (real_name); @@ -4062,12 +4125,11 @@ ppc_extern (int ignore ATTRIBUTE_UNUSED) char *name; char endc; - name = input_line_pointer; - endc = get_symbol_end (); + endc = get_symbol_name (&name); (void) symbol_find_or_make (name); - *input_line_pointer = endc; + (void) restore_line_pointer (endc); demand_empty_rest_of_line (); } @@ -4081,12 +4143,11 @@ ppc_lglobl (int ignore ATTRIBUTE_UNUSED) char endc; symbolS *sym; - name = input_line_pointer; - endc = get_symbol_end (); + endc = get_symbol_name (&name); sym = symbol_find_or_make (name); - *input_line_pointer = endc; + (void) restore_line_pointer (endc); symbol_get_tc (sym)->output = 1; @@ -4119,14 +4180,13 @@ ppc_ref (int ignore ATTRIBUTE_UNUSED) do { - name = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (&name); fix_at_start (symbol_get_frag (ppc_current_csect), 0, symbol_find_or_make (name), 0, FALSE, BFD_RELOC_NONE); *input_line_pointer = c; - SKIP_WHITESPACE (); + SKIP_WHITESPACE_AFTER_NAME (); c = *input_line_pointer; if (c == ',') { @@ -4156,12 +4216,11 @@ ppc_rename (int ignore ATTRIBUTE_UNUSED) symbolS *sym; int len; - name = input_line_pointer; - endc = get_symbol_end (); + endc = get_symbol_name (&name); sym = symbol_find_or_make (name); - *input_line_pointer = endc; + (void) restore_line_pointer (endc); if (*input_line_pointer != ',') { @@ -4320,8 +4379,7 @@ ppc_function (int ignore ATTRIBUTE_UNUSED) symbolS *ext_sym; symbolS *lab_sym; - name = input_line_pointer; - endc = get_symbol_end (); + endc = get_symbol_name (&name); /* Ignore any [PR] suffix. */ name = ppc_canonicalize_symbol_name (name); @@ -4332,7 +4390,7 @@ ppc_function (int ignore ATTRIBUTE_UNUSED) ext_sym = symbol_find_or_make (name); - *input_line_pointer = endc; + (void) restore_line_pointer (endc); if (*input_line_pointer != ',') { @@ -4342,12 +4400,11 @@ ppc_function (int ignore ATTRIBUTE_UNUSED) } ++input_line_pointer; - name = input_line_pointer; - endc = get_symbol_end (); + endc = get_symbol_name (&name); lab_sym = symbol_find_or_make (name); - *input_line_pointer = endc; + (void) restore_line_pointer (endc); if (ext_sym != lab_sym) { @@ -4526,12 +4583,11 @@ ppc_bs (int ignore ATTRIBUTE_UNUSED) if (ppc_current_block != NULL) as_bad (_("nested .bs blocks")); - name = input_line_pointer; - endc = get_symbol_end (); + endc = get_symbol_name (&name); csect = symbol_find_or_make (name); - *input_line_pointer = endc; + (void) restore_line_pointer (endc); sym = symbol_make (".bs"); S_SET_SEGMENT (sym, now_seg); @@ -4808,12 +4864,11 @@ ppc_tc (int ignore ATTRIBUTE_UNUSED) return; } - name = input_line_pointer; - endc = get_symbol_end (); + endc = get_symbol_name (&name); sym = symbol_find_or_make (name); - *input_line_pointer = endc; + (void) restore_line_pointer (endc); if (S_IS_DEFINED (sym)) { @@ -4879,6 +4934,7 @@ ppc_tc (int ignore ATTRIBUTE_UNUSED) static void ppc_machine (int ignore ATTRIBUTE_UNUSED) { + char c; char *cpu_string; #define MAX_HISTORY 100 static ppc_cpu_t *cpu_history; @@ -4886,19 +4942,9 @@ ppc_machine (int ignore ATTRIBUTE_UNUSED) SKIP_WHITESPACE (); - if (*input_line_pointer == '"') - { - int len; - cpu_string = demand_copy_C_string (&len); - } - else - { - char c; - cpu_string = input_line_pointer; - c = get_symbol_end (); - cpu_string = xstrdup (cpu_string); - *input_line_pointer = c; - } + c = get_symbol_name (&cpu_string); + cpu_string = xstrdup (cpu_string); + (void) restore_line_pointer (c); if (cpu_string != NULL) { @@ -4912,7 +4958,7 @@ ppc_machine (int ignore ATTRIBUTE_UNUSED) if (strcmp (cpu_string, "push") == 0) { if (cpu_history == NULL) - cpu_history = xmalloc (MAX_HISTORY * sizeof (*cpu_history)); + cpu_history = XNEWVEC (ppc_cpu_t, MAX_HISTORY); if (curr_hist >= MAX_HISTORY) as_bad (_(".machine stack overflow")); @@ -5137,17 +5183,15 @@ ppc_znop (int ignore ATTRIBUTE_UNUSED) char *name; /* Strip out the symbol name. */ - symbol_name = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (&symbol_name); - name = xmalloc (input_line_pointer - symbol_name + 1); - strcpy (name, symbol_name); + name = xstrdup (symbol_name); sym = symbol_find_or_make (name); *input_line_pointer = c; - SKIP_WHITESPACE (); + SKIP_WHITESPACE_AFTER_NAME (); /* Look up the opcode in the hash table. */ opcode = (const struct powerpc_opcode *) hash_find (ppc_hash, "nop"); @@ -5183,13 +5227,12 @@ ppc_pe_comm (int lcomm) symbolS *symbolP; offsetT align; - name = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (&name); /* just after name is now '\0'. */ p = input_line_pointer; *p = c; - SKIP_WHITESPACE (); + SKIP_WHITESPACE_AFTER_NAME (); if (*input_line_pointer != ',') { as_bad (_("expected comma after symbol-name: rest of line ignored.")); @@ -5314,15 +5357,13 @@ ppc_pe_section (int ignore ATTRIBUTE_UNUSED) segT sec; int align; - section_name = input_line_pointer; - c = get_symbol_end (); + c = get_symbol_name (§ion_name); - name = xmalloc (input_line_pointer - section_name + 1); - strcpy (name, section_name); + name = xstrdup (section_name); *input_line_pointer = c; - SKIP_WHITESPACE (); + SKIP_WHITESPACE_AFTER_NAME (); exp = 0; flags = SEC_NO_FLAGS; @@ -5470,12 +5511,11 @@ ppc_pe_function (int ignore ATTRIBUTE_UNUSED) char endc; symbolS *ext_sym; - name = input_line_pointer; - endc = get_symbol_end (); + endc = get_symbol_name (&name); ext_sym = symbol_find_or_make (name); - *input_line_pointer = endc; + (void) restore_line_pointer (endc); S_SET_DATA_TYPE (ext_sym, DT_FCN << N_BTSHFT); SF_SET_FUNCTION (ext_sym); @@ -5716,9 +5756,7 @@ ppc_frob_symbol (symbolS *sym) char *snew; len = s - name; - snew = xmalloc (len + 1); - memcpy (snew, name, len); - snew[len] = '\0'; + snew = xstrndup (name, len); S_SET_NAME (sym, snew); } @@ -6017,7 +6055,7 @@ ppc_frob_section (asection *sec) #endif /* OBJ_XCOFF */ -char * +const char * md_atof (int type, char *litp, int *sizep) { return ieee_md_atof (type, litp, sizep, target_big_endian); @@ -6045,7 +6083,7 @@ md_section_align (asection *seg ATTRIBUTE_UNUSED, valueT addr) #else int align = bfd_get_section_alignment (stdoutput, seg); - return ((addr + (1 << align) - 1) & (-1 << align)); + return ((addr + (1 << align) - 1) & -(1 << align)); #endif } @@ -6370,13 +6408,14 @@ ppc_handle_align (struct frag *fragP) if ((ppc_cpu & PPC_OPCODE_POWER6) != 0 || (ppc_cpu & PPC_OPCODE_POWER7) != 0 - || (ppc_cpu & PPC_OPCODE_POWER8) != 0) + || (ppc_cpu & PPC_OPCODE_POWER8) != 0 + || (ppc_cpu & PPC_OPCODE_POWER9) != 0) { - /* For power6, power7 and power8, we want the last nop to be a group - terminating one. Do this by inserting an rs_fill frag immediately - after this one, with its address set to the last nop location. - This will automatically reduce the number of nops in the current - frag by one. */ + /* For power6, power7, power8 and power9, we want the last nop to be + a group terminating one. Do this by inserting an rs_fill frag + immediately after this one, with its address set to the last nop + location. This will automatically reduce the number of nops in + the current frag by one. */ if (count > 4) { struct frag *group_nop = xmalloc (SIZEOF_STRUCT_FRAG + 4); @@ -6391,13 +6430,14 @@ ppc_handle_align (struct frag *fragP) } if ((ppc_cpu & PPC_OPCODE_POWER7) != 0 - || (ppc_cpu & PPC_OPCODE_POWER8) != 0) + || (ppc_cpu & PPC_OPCODE_POWER8) != 0 + || (ppc_cpu & PPC_OPCODE_POWER9) != 0) { if (ppc_cpu & PPC_OPCODE_E500MC) /* e500mc group terminating nop: "ori 0,0,0". */ md_number_to_chars (dest, 0x60000000, 4); else - /* power7/power8 group terminating nop: "ori 2,2,0". */ + /* power7/power8/power9 group terminating nop: "ori 2,2,0". */ md_number_to_chars (dest, 0x60420000, 4); } else @@ -6423,6 +6463,9 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) /* Hack around bfd_install_relocation brain damage. */ if (fixP->fx_pcrel) value += fixP->fx_frag->fr_address + fixP->fx_where; + + if (fixP->fx_addsy == abs_section_sym) + fixP->fx_done = 1; } else fixP->fx_done = 1; @@ -6533,6 +6576,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) case BFD_RELOC_HI16_S: case BFD_RELOC_HI16_S_PCREL: + case BFD_RELOC_PPC_REL16DX_HA: #ifdef OBJ_ELF if (REPORT_OVERFLOW_HI && ppc_obj64) { @@ -6578,9 +6622,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) if (operand != NULL) { /* Handle relocs in an insn. */ - char *where; - unsigned long insn; - switch (fixP->fx_r_type) { #ifdef OBJ_ELF @@ -6705,6 +6746,29 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) break; #endif + case BFD_RELOC_VTABLE_INHERIT: + case BFD_RELOC_VTABLE_ENTRY: + case BFD_RELOC_PPC_DTPMOD: + case BFD_RELOC_PPC_TPREL: + case BFD_RELOC_PPC_DTPREL: + case BFD_RELOC_PPC_COPY: + case BFD_RELOC_PPC_GLOB_DAT: + case BFD_RELOC_32_PLT_PCREL: + case BFD_RELOC_PPC_EMB_NADDR32: + case BFD_RELOC_PPC64_TOC: + case BFD_RELOC_CTOR: + case BFD_RELOC_32: + case BFD_RELOC_32_PCREL: + case BFD_RELOC_RVA: + case BFD_RELOC_64: + case BFD_RELOC_64_PCREL: + case BFD_RELOC_PPC64_ADDR64_LOCAL: + as_bad_where (fixP->fx_file, fixP->fx_line, + _("%s unsupported as instruction fixup"), + bfd_get_reloc_code_name (fixP->fx_r_type)); + fixP->fx_done = 1; + return; + default: break; } @@ -6718,22 +6782,25 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) #endif if ((fieldval != 0 && APPLY_RELOC) || operand->insert != NULL) { + unsigned long insn; + unsigned char *where; + /* Fetch the instruction, insert the fully resolved operand value, and stuff the instruction back again. */ - where = fixP->fx_frag->fr_literal + fixP->fx_where; + where = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where; if (target_big_endian) { if (fixP->fx_size == 4) - insn = bfd_getb32 ((unsigned char *) where); + insn = bfd_getb32 (where); else - insn = bfd_getb16 ((unsigned char *) where); + insn = bfd_getb16 (where); } else { if (fixP->fx_size == 4) - insn = bfd_getl32 ((unsigned char *) where); + insn = bfd_getl32 (where); else - insn = bfd_getl16 ((unsigned char *) where); + insn = bfd_getl16 (where); } insn = ppc_insert_operand (insn, operand, fieldval, fixP->tc_fix_data.ppc_cpu, @@ -6741,16 +6808,16 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) if (target_big_endian) { if (fixP->fx_size == 4) - bfd_putb32 ((bfd_vma) insn, (unsigned char *) where); + bfd_putb32 (insn, where); else - bfd_putb16 ((bfd_vma) insn, (unsigned char *) where); + bfd_putb16 (insn, where); } else { if (fixP->fx_size == 4) - bfd_putl32 ((bfd_vma) insn, (unsigned char *) where); + bfd_putl32 (insn, where); else - bfd_putl16 ((bfd_vma) insn, (unsigned char *) where); + bfd_putl16 (insn, where); } } @@ -6761,7 +6828,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) gas_assert (fixP->fx_addsy != NULL); if (fixP->fx_r_type == BFD_RELOC_NONE) { - char *sfile; + const char *sfile; unsigned int sline; /* Use expr_symbol_where to see if this is an expression @@ -6924,6 +6991,16 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) if (fixP->fx_size && APPLY_RELOC) md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where, fieldval, fixP->fx_size); + if (warn_476 + && (seg->flags & SEC_CODE) != 0 + && fixP->fx_size == 4 + && fixP->fx_done + && !fixP->fx_tcbit + && (fixP->fx_r_type == BFD_RELOC_32 + || fixP->fx_r_type == BFD_RELOC_CTOR + || fixP->fx_r_type == BFD_RELOC_32_PCREL)) + as_warn_where (fixP->fx_file, fixP->fx_line, + _("data in executable section")); } /* We are only able to convert some relocs to pc-relative. */ @@ -6959,6 +7036,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) case BFD_RELOC_LO16_PCREL: case BFD_RELOC_HI16_PCREL: case BFD_RELOC_HI16_S_PCREL: + case BFD_RELOC_PPC_REL16DX_HA: case BFD_RELOC_64_PCREL: case BFD_RELOC_32_PCREL: case BFD_RELOC_16_PCREL: @@ -6978,7 +7056,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg) default: if (fixP->fx_addsy) { - char *sfile; + const char *sfile; unsigned int sline; /* Use expr_symbol_where to see if this is an @@ -7049,9 +7127,9 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) { arelent *reloc; - reloc = (arelent *) xmalloc (sizeof (arelent)); + reloc = XNEW (arelent); - reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + 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; reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); @@ -7080,7 +7158,7 @@ tc_ppc_regname_to_dw2regnum (char *regname) unsigned int i; const char *p; char *q; - static struct { char *name; int dw2regnum; } regnames[] = + static struct { const char *name; int dw2regnum; } regnames[] = { { "sp", 1 }, { "r.sp", 1 }, { "rtoc", 2 }, { "r.toc", 2 }, { "mq", 64 }, { "lr", 65 }, { "ctr", 66 }, { "ap", 67 },