/* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
- Copyright (C) 1994-2014 Free Software Foundation, Inc.
+ Copyright (C) 1994-2015 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of GAS, the GNU Assembler.
has_large_toc_reloc = 1,
has_small_toc_reloc = 2
} toc_reloc_types;
+
+/* Warn on emitting data to code sections. */
+int warn_476;
+unsigned long last_insn;
+segT last_seg;
+subsegT last_subseg;
\f
/* The target specific pseudo-ops which we support. */
#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);
}
break;
+ case 0:
+ break;
+
default:
return 0;
}
-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"));
}
\f
/* Set ppc_cpu if it is not already set. */
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 [-65536, 65535].
+ Similarly for 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.
+ Use the same extended range for cmpli, to allow at least
+ [-32768, 65535]. */
+ min = ~max & -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;
}
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)
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
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);
static void
ppc_byte (int ignore ATTRIBUTE_UNUSED)
{
+ int count = 0;
+
if (*input_line_pointer != '\"')
{
cons (1);
}
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 ();
}
\f
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. */