/* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
- Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- Free Software Foundation, Inc.
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004, 2005 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of GAS, the GNU Assembler.
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to the Free
- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
#include <stdio.h>
#include "as.h"
#include "safe-ctype.h"
#include "subsegs.h"
-
+#include "dw2gencfi.h"
#include "opcode/ppc.h"
#ifdef OBJ_ELF
static void ppc_ef PARAMS ((int));
static void ppc_es PARAMS ((int));
static void ppc_csect PARAMS ((int));
-static void ppc_change_csect PARAMS ((symbolS *));
+static void ppc_change_csect PARAMS ((symbolS *, offsetT));
static void ppc_function PARAMS ((int));
static void ppc_extern PARAMS ((int));
static void ppc_lglobl PARAMS ((int));
as in 0d1.0. */
const char FLT_CHARS[] = "dD";
-/* '+' and '-' can be used as postfix predicate predictors for conditional
- branches. So they need to be accepted as symbol characters. */
-const char ppc_symbol_chars[] = "+-";
+/* '+' and '-' can be used as postfix predicate predictors for conditional
+ branches. So they need to be accepted as symbol characters.
+ Also, anything that can start an operand needs to be mentioned here,
+ to stop the input scrubber eating whitespace. */
+const char ppc_symbol_chars[] = "+-%[";
+
+/* The dwarf2 data alignment, adjusted for 32 or 64 bit. */
+int ppc_cie_data_alignment;
\f
/* The target specific pseudo-ops which we support. */
{ "rdata", ppc_elf_rdata, 0 },
{ "rodata", ppc_elf_rdata, 0 },
{ "lcomm", ppc_elf_lcomm, 0 },
- { "file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
- { "loc", dwarf2_directive_loc, 0 },
#endif
#ifdef TE_PE
};
const size_t md_longopts_size = sizeof (md_longopts);
+
+/* Handle -m options that set cpu type, and .machine arg. */
+
+static int
+parse_cpu (const char *arg)
+{
+ /* -mpwrx and -mpwr2 mean to assemble for the IBM POWER/2
+ (RIOS2). */
+ if (strcmp (arg, "pwrx") == 0 || strcmp (arg, "pwr2") == 0)
+ ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_32;
+ /* -mpwr means to assemble for the IBM POWER (RIOS1). */
+ else if (strcmp (arg, "pwr") == 0)
+ ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
+ /* -m601 means to assemble for the PowerPC 601, which includes
+ instructions that are holdovers from the Power. */
+ else if (strcmp (arg, "601") == 0)
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+ | PPC_OPCODE_601 | PPC_OPCODE_32);
+ /* -mppc, -mppc32, -m603, and -m604 mean to assemble for the
+ PowerPC 603/604. */
+ else if (strcmp (arg, "ppc") == 0
+ || strcmp (arg, "ppc32") == 0
+ || strcmp (arg, "603") == 0
+ || strcmp (arg, "604") == 0)
+ ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
+ /* -m403 and -m405 mean to assemble for the PowerPC 403/405. */
+ else if (strcmp (arg, "403") == 0
+ || strcmp (arg, "405") == 0)
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+ | PPC_OPCODE_403 | PPC_OPCODE_32);
+ else if (strcmp (arg, "440") == 0)
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32
+ | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI);
+ else if (strcmp (arg, "7400") == 0
+ || strcmp (arg, "7410") == 0
+ || strcmp (arg, "7450") == 0
+ || strcmp (arg, "7455") == 0)
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+ | PPC_OPCODE_ALTIVEC | PPC_OPCODE_32);
+ else if (strcmp (arg, "e300") == 0)
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32
+ | PPC_OPCODE_E300);
+ else if (strcmp (arg, "altivec") == 0)
+ {
+ if (ppc_cpu == 0)
+ ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC;
+ else
+ ppc_cpu |= PPC_OPCODE_ALTIVEC;
+ }
+ else if (strcmp (arg, "e500") == 0 || strcmp (arg, "e500x2") == 0)
+ {
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
+ | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
+ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
+ | PPC_OPCODE_RFMCI);
+ }
+ else if (strcmp (arg, "spe") == 0)
+ {
+ if (ppc_cpu == 0)
+ ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_SPE | PPC_OPCODE_EFS;
+ else
+ ppc_cpu |= PPC_OPCODE_SPE;
+ }
+ /* -mppc64 and -m620 mean to assemble for the 64-bit PowerPC
+ 620. */
+ else if (strcmp (arg, "ppc64") == 0 || strcmp (arg, "620") == 0)
+ {
+ ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
+ }
+ else if (strcmp (arg, "ppc64bridge") == 0)
+ {
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+ | PPC_OPCODE_64_BRIDGE | PPC_OPCODE_64);
+ }
+ /* -mbooke/-mbooke32 mean enable 32-bit BookE support. */
+ else if (strcmp (arg, "booke") == 0 || strcmp (arg, "booke32") == 0)
+ {
+ ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32;
+ }
+ /* -mbooke64 means enable 64-bit BookE support. */
+ else if (strcmp (arg, "booke64") == 0)
+ {
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE
+ | PPC_OPCODE_BOOKE64 | PPC_OPCODE_64);
+ }
+ else if (strcmp (arg, "power4") == 0)
+ {
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+ | PPC_OPCODE_64 | PPC_OPCODE_POWER4);
+ }
+ else if (strcmp (arg, "power5") == 0)
+ {
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+ | PPC_OPCODE_64 | PPC_OPCODE_POWER4
+ | PPC_OPCODE_POWER5);
+ }
+ /* -mcom means assemble for the common intersection between Power
+ and PowerPC. At present, we just allow the union, rather
+ than the intersection. */
+ else if (strcmp (arg, "com") == 0)
+ ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
+ /* -many means to assemble for any architecture (PWR/PWRX/PPC). */
+ else if (strcmp (arg, "any") == 0)
+ ppc_cpu |= PPC_OPCODE_ANY;
+ else
+ return 0;
+
+ return 1;
+}
+
int
md_parse_option (c, arg)
int c;
break;
case 'm':
- /* -mpwrx and -mpwr2 mean to assemble for the IBM POWER/2
- (RIOS2). */
- if (strcmp (arg, "pwrx") == 0 || strcmp (arg, "pwr2") == 0)
- ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_32;
- /* -mpwr means to assemble for the IBM POWER (RIOS1). */
- else if (strcmp (arg, "pwr") == 0)
- ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
- /* -m601 means to assemble for the PowerPC 601, which includes
- instructions that are holdovers from the Power. */
- else if (strcmp (arg, "601") == 0)
- ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
- | PPC_OPCODE_601 | PPC_OPCODE_32);
- /* -mppc, -mppc32, -m603, and -m604 mean to assemble for the
- PowerPC 603/604. */
- else if (strcmp (arg, "ppc") == 0
- || strcmp (arg, "ppc32") == 0
- || strcmp (arg, "603") == 0
- || strcmp (arg, "604") == 0)
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
- /* -m403 and -m405 mean to assemble for the PowerPC 403/405. */
- else if (strcmp (arg, "403") == 0
- || strcmp (arg, "405") == 0)
- ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
- | PPC_OPCODE_403 | PPC_OPCODE_32);
- else if (strcmp (arg, "7400") == 0
- || strcmp (arg, "7410") == 0
- || strcmp (arg, "7450") == 0
- || strcmp (arg, "7455") == 0)
- ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
- | PPC_OPCODE_ALTIVEC | PPC_OPCODE_32);
- else if (strcmp (arg, "altivec") == 0)
- {
- if (ppc_cpu == 0)
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC;
- else
- ppc_cpu |= PPC_OPCODE_ALTIVEC;
- }
- else if (strcmp (arg, "e500") == 0 || strcmp (arg, "e500x2") == 0)
- {
- ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
- | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
- | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
- | PPC_OPCODE_RFMCI);
- }
- else if (strcmp (arg, "spe") == 0)
- {
- if (ppc_cpu == 0)
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_SPE | PPC_OPCODE_EFS;
- else
- ppc_cpu |= PPC_OPCODE_SPE;
- }
- /* -mppc64 and -m620 mean to assemble for the 64-bit PowerPC
- 620. */
- else if (strcmp (arg, "ppc64") == 0 || strcmp (arg, "620") == 0)
- {
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
- }
- else if (strcmp (arg, "ppc64bridge") == 0)
- {
- ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
- | PPC_OPCODE_64_BRIDGE | PPC_OPCODE_64);
- }
- /* -mbooke/-mbooke32 mean enable 32-bit BookE support. */
- else if (strcmp (arg, "booke") == 0 || strcmp (arg, "booke32") == 0)
- {
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32;
- }
- /* -mbooke64 means enable 64-bit BookE support. */
- else if (strcmp (arg, "booke64") == 0)
- {
- ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE
- | PPC_OPCODE_BOOKE64 | PPC_OPCODE_64);
- }
- else if (strcmp (arg, "power4") == 0)
- {
- ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
- | PPC_OPCODE_64 | PPC_OPCODE_POWER4);
- }
- /* -mcom means assemble for the common intersection between Power
- and PowerPC. At present, we just allow the union, rather
- than the intersection. */
- else if (strcmp (arg, "com") == 0)
- ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
- /* -many means to assemble for any architecture (PWR/PWRX/PPC). */
- else if (strcmp (arg, "any") == 0)
- ppc_cpu = PPC_OPCODE_ANY | PPC_OPCODE_32;
+ if (parse_cpu (arg))
+ ;
else if (strcmp (arg, "regnames") == 0)
reg_names_p = TRUE;
{
fprintf (stream, _("\
PowerPC options:\n\
+-a32 generate ELF32/XCOFF32\n\
+-a64 generate ELF64/XCOFF64\n\
-u ignored\n\
-mpwrx, -mpwr2 generate code for POWER/2 (RIOS2)\n\
-mpwr generate code for POWER (RIOS1)\n\
-m601 generate code for PowerPC 601\n\
-mppc, -mppc32, -m603, -m604\n\
generate code for PowerPC 603/604\n\
--m403, -m405 generate code for PowerPC 403/405\n\
+-m403, -m405 generate code for PowerPC 403/405\n\
+-m440 generate code for PowerPC 440\n\
-m7400, -m7410, -m7450, -m7455\n\
- generate code For PowerPC 7400/7410/7450/7455\n\
+ generate code For PowerPC 7400/7410/7450/7455\n"));
+ fprintf (stream, _("\
-mppc64, -m620 generate code for PowerPC 620/625/630\n\
-mppc64bridge generate code for PowerPC 64, including bridge insns\n\
-mbooke64 generate code for 64-bit PowerPC BookE\n\
-mbooke, mbooke32 generate code for 32-bit PowerPC BookE\n\
-mpower4 generate code for Power4 architecture\n\
--maltivec generate code for AltiVec\n\
+-mpower5 generate code for Power5 architecture\n\
-mcom generate code Power/PowerPC common instructions\n\
--many generate code for any architecture (PWR/PWRX/PPC)\n\
--mregnames Allow symbolic names for registers\n\
--mno-regnames Do not allow symbolic names for registers\n"));
+-many generate code for any architecture (PWR/PWRX/PPC)\n"));
fprintf (stream, _("\
+-maltivec generate code for AltiVec\n\
+-me300 generate code for PowerPC e300 family\n\
-me500, -me500x2 generate code for Motorola e500 core complex\n\
--mspe generate code for Motorola SPE instructions\n"));
+-mspe generate code for Motorola SPE instructions\n\
+-mregnames Allow symbolic names for registers\n\
+-mno-regnames Do not allow symbolic names for registers\n"));
#ifdef OBJ_ELF
fprintf (stream, _("\
-mrelocatable support for GCC's -mrelocatble option\n\
-mrelocatable-lib support for GCC's -mrelocatble-lib option\n\
-memb set PPC_EMB bit in ELF flags\n\
--mlittle, -mlittle-endian\n\
+-mlittle, -mlittle-endian, -l, -le\n\
generate code for a little endian machine\n\
--mbig, -mbig-endian generate code for a big endian machine\n\
+-mbig, -mbig-endian, -b, -be\n\
+ generate code for a big endian machine\n\
-msolaris generate code for Solaris\n\
-mno-solaris do not generate code for Solaris\n\
-V print assembler version number\n\
const char *default_os = TARGET_OS;
const char *default_cpu = TARGET_CPU;
- if (ppc_cpu == 0)
+ if ((ppc_cpu & ~PPC_OPCODE_ANY) == 0)
{
if (ppc_obj64)
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
+ ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
else if (strncmp (default_os, "aix", 3) == 0
&& default_os[3] >= '4' && default_os[3] <= '9')
- ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
+ ppc_cpu |= PPC_OPCODE_COMMON | PPC_OPCODE_32;
else if (strncmp (default_os, "aix3", 4) == 0)
- ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
+ ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
else if (strcmp (default_cpu, "rs6000") == 0)
- ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
+ ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
else if (strncmp (default_cpu, "powerpc", 7) == 0)
- {
- if (default_cpu[7] == '6' && default_cpu[8] == '4')
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
- else
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
- }
+ ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
else
as_fatal (_("Unknown default cpu = %s, os = %s"),
default_cpu, default_os);
}
}
-/* Figure out the BFD architecture to use. */
+/* Figure out the BFD architecture to use. This function and ppc_mach
+ are called well before md_begin, when the output file is opened. */
enum bfd_architecture
ppc_arch ()
#endif
#endif
#ifdef OBJ_ELF
+# ifdef TE_VXWORKS
+ return "elf32-powerpc-vxworks";
+# else
return (target_big_endian
? (ppc_obj64 ? "elf64-powerpc" : "elf32-powerpc")
: (ppc_obj64 ? "elf64-powerpcle" : "elf32-powerpcle"));
+# endif
#endif
}
-/* This function is called when the assembler starts up. It is called
- after the options have been parsed and the output file has been
- opened. */
+/* Insert opcodes and macros into hash tables. Called at startup and
+ for .cpu pseudo. */
-void
-md_begin ()
+static void
+ppc_setup_opcodes (void)
{
register const struct powerpc_opcode *op;
const struct powerpc_opcode *op_end;
const struct powerpc_macro *macro_end;
bfd_boolean dup_insn = FALSE;
- ppc_set_cpu ();
-
-#ifdef OBJ_ELF
- /* Set the ELF flags if desired. */
- if (ppc_flags && !msolaris)
- bfd_set_private_flags (stdoutput, ppc_flags);
-#endif
+ if (ppc_hash != NULL)
+ hash_die (ppc_hash);
+ if (ppc_macro_hash != NULL)
+ hash_die (ppc_macro_hash);
/* Insert the opcodes into a hash table. */
ppc_hash = hash_new ();
|| (ppc_cpu & PPC_OPCODE_BOOKE) == 0)
&& ((op->flags & (PPC_OPCODE_POWER4 | PPC_OPCODE_NOPOWER4)) == 0
|| ((op->flags & PPC_OPCODE_POWER4)
- == (ppc_cpu & PPC_OPCODE_POWER4))))
+ == (ppc_cpu & PPC_OPCODE_POWER4)))
+ && ((op->flags & PPC_OPCODE_POWER5) == 0
+ || ((op->flags & PPC_OPCODE_POWER5)
+ == (ppc_cpu & PPC_OPCODE_POWER5))))
{
const char *retval;
retval = hash_insert (ppc_hash, op->name, (PTR) op);
- if (retval != (const char *) NULL)
+ if (retval != NULL)
{
/* Ignore Power duplicates for -m601. */
if ((ppc_cpu & PPC_OPCODE_601) != 0
}
}
+ if ((ppc_cpu & PPC_OPCODE_ANY) != 0)
+ for (op = powerpc_opcodes; op < op_end; op++)
+ hash_insert (ppc_hash, op->name, (PTR) op);
+
/* Insert the macros into a hash table. */
ppc_macro_hash = hash_new ();
if (dup_insn)
abort ();
+}
+
+/* This function is called when the assembler starts up. It is called
+ after the options have been parsed and the output file has been
+ opened. */
+
+void
+md_begin ()
+{
+ ppc_set_cpu ();
+
+ ppc_cie_data_alignment = ppc_obj64 ? -8 : -4;
+
+#ifdef OBJ_ELF
+ /* Set the ELF flags if desired. */
+ if (ppc_flags && !msolaris)
+ bfd_set_private_flags (stdoutput, ppc_flags);
+#endif
+
+ ppc_setup_opcodes ();
- /* Tell the main code what the endianness is if it is not overidden
+ /* Tell the main code what the endianness is if it is not overridden
by the user. */
if (!set_target_endian)
{
md_number_to_chars (p, (valueT) 8, 4);
p = frag_more (4);
- md_number_to_chars (p, (valueT) ppc_apuinfo_num, 4);
+ md_number_to_chars (p, (valueT) ppc_apuinfo_num * 4, 4);
p = frag_more (4);
md_number_to_chars (p, (valueT) 2, 4);
test = val;
if (test < (offsetT) min || test > (offsetT) max)
- {
- const char *err =
- _("operand out of range (%s not between %ld and %ld)");
- char buf[100];
-
- sprint_value (buf, test);
- as_bad_where (file, line, err, buf, min, max);
- }
+ as_bad_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line);
}
if (operand->insert)
{
struct map_bfd {
char *string;
- int length;
- int reloc;
+ unsigned int length : 8;
+ unsigned int valid32 : 1;
+ unsigned int valid64 : 1;
+ unsigned int reloc;
};
char ident[20];
int len;
const struct map_bfd *ptr;
-#define MAP(str,reloc) { str, sizeof (str)-1, reloc }
+#define MAP(str, reloc) { str, sizeof (str) - 1, 1, 1, reloc }
+#define MAP32(str, reloc) { str, sizeof (str) - 1, 1, 0, reloc }
+#define MAP64(str, reloc) { str, sizeof (str) - 1, 0, 1, reloc }
static const struct map_bfd mapping[] = {
- MAP ("l", (int) BFD_RELOC_LO16),
- MAP ("h", (int) BFD_RELOC_HI16),
- MAP ("ha", (int) BFD_RELOC_HI16_S),
- MAP ("brtaken", (int) BFD_RELOC_PPC_B16_BRTAKEN),
- MAP ("brntaken", (int) BFD_RELOC_PPC_B16_BRNTAKEN),
- MAP ("got", (int) BFD_RELOC_16_GOTOFF),
- MAP ("got@l", (int) BFD_RELOC_LO16_GOTOFF),
- MAP ("got@h", (int) BFD_RELOC_HI16_GOTOFF),
- MAP ("got@ha", (int) BFD_RELOC_HI16_S_GOTOFF),
- MAP ("fixup", (int) BFD_RELOC_CTOR),
- MAP ("plt", (int) BFD_RELOC_24_PLT_PCREL),
- MAP ("pltrel24", (int) BFD_RELOC_24_PLT_PCREL),
- MAP ("copy", (int) BFD_RELOC_PPC_COPY),
- MAP ("globdat", (int) BFD_RELOC_PPC_GLOB_DAT),
- MAP ("local24pc", (int) BFD_RELOC_PPC_LOCAL24PC),
- MAP ("local", (int) BFD_RELOC_PPC_LOCAL24PC),
- MAP ("pltrel", (int) BFD_RELOC_32_PLT_PCREL),
- MAP ("plt@l", (int) BFD_RELOC_LO16_PLTOFF),
- MAP ("plt@h", (int) BFD_RELOC_HI16_PLTOFF),
- MAP ("plt@ha", (int) BFD_RELOC_HI16_S_PLTOFF),
- MAP ("sdarel", (int) BFD_RELOC_GPREL16),
- MAP ("sectoff", (int) BFD_RELOC_16_BASEREL),
- MAP ("sectoff@l", (int) BFD_RELOC_LO16_BASEREL),
- MAP ("sectoff@h", (int) BFD_RELOC_HI16_BASEREL),
- MAP ("sectoff@ha", (int) BFD_RELOC_HI16_S_BASEREL),
- MAP ("naddr", (int) BFD_RELOC_PPC_EMB_NADDR32),
- MAP ("naddr16", (int) BFD_RELOC_PPC_EMB_NADDR16),
- MAP ("naddr@l", (int) BFD_RELOC_PPC_EMB_NADDR16_LO),
- MAP ("naddr@h", (int) BFD_RELOC_PPC_EMB_NADDR16_HI),
- MAP ("naddr@ha", (int) BFD_RELOC_PPC_EMB_NADDR16_HA),
- MAP ("sdai16", (int) BFD_RELOC_PPC_EMB_SDAI16),
- MAP ("sda2rel", (int) BFD_RELOC_PPC_EMB_SDA2REL),
- MAP ("sda2i16", (int) BFD_RELOC_PPC_EMB_SDA2I16),
- MAP ("sda21", (int) BFD_RELOC_PPC_EMB_SDA21),
- MAP ("mrkref", (int) BFD_RELOC_PPC_EMB_MRKREF),
- MAP ("relsect", (int) BFD_RELOC_PPC_EMB_RELSEC16),
- MAP ("relsect@l", (int) BFD_RELOC_PPC_EMB_RELST_LO),
- MAP ("relsect@h", (int) BFD_RELOC_PPC_EMB_RELST_HI),
- MAP ("relsect@ha", (int) BFD_RELOC_PPC_EMB_RELST_HA),
- MAP ("bitfld", (int) BFD_RELOC_PPC_EMB_BIT_FLD),
- MAP ("relsda", (int) BFD_RELOC_PPC_EMB_RELSDA),
- MAP ("xgot", (int) BFD_RELOC_PPC_TOC16),
- MAP ("tls", (int) BFD_RELOC_PPC_TLS),
- MAP ("dtpmod", (int) BFD_RELOC_PPC_DTPMOD),
- MAP ("dtprel", (int) BFD_RELOC_PPC_DTPREL),
- MAP ("dtprel@l", (int) BFD_RELOC_PPC_DTPREL16_LO),
- MAP ("dtprel@h", (int) BFD_RELOC_PPC_DTPREL16_HI),
- MAP ("dtprel@ha", (int) BFD_RELOC_PPC_DTPREL16_HA),
- MAP ("tprel", (int) BFD_RELOC_PPC_TPREL),
- MAP ("tprel@l", (int) BFD_RELOC_PPC_TPREL16_LO),
- MAP ("tprel@h", (int) BFD_RELOC_PPC_TPREL16_HI),
- MAP ("tprel@ha", (int) BFD_RELOC_PPC_TPREL16_HA),
- MAP ("got@tlsgd", (int) BFD_RELOC_PPC_GOT_TLSGD16),
- MAP ("got@tlsgd@l", (int) BFD_RELOC_PPC_GOT_TLSGD16_LO),
- MAP ("got@tlsgd@h", (int) BFD_RELOC_PPC_GOT_TLSGD16_HI),
- MAP ("got@tlsgd@ha", (int) BFD_RELOC_PPC_GOT_TLSGD16_HA),
- MAP ("got@tlsld", (int) BFD_RELOC_PPC_GOT_TLSLD16),
- MAP ("got@tlsld@l", (int) BFD_RELOC_PPC_GOT_TLSLD16_LO),
- MAP ("got@tlsld@h", (int) BFD_RELOC_PPC_GOT_TLSLD16_HI),
- MAP ("got@tlsld@ha", (int) BFD_RELOC_PPC_GOT_TLSLD16_HA),
- MAP ("got@dtprel", (int) BFD_RELOC_PPC_GOT_DTPREL16),
- MAP ("got@dtprel@l", (int) BFD_RELOC_PPC_GOT_DTPREL16_LO),
- MAP ("got@dtprel@h", (int) BFD_RELOC_PPC_GOT_DTPREL16_HI),
- MAP ("got@dtprel@ha", (int) BFD_RELOC_PPC_GOT_DTPREL16_HA),
- MAP ("got@tprel", (int) BFD_RELOC_PPC_GOT_TPREL16),
- MAP ("got@tprel@l", (int) BFD_RELOC_PPC_GOT_TPREL16_LO),
- MAP ("got@tprel@h", (int) BFD_RELOC_PPC_GOT_TPREL16_HI),
- MAP ("got@tprel@ha", (int) BFD_RELOC_PPC_GOT_TPREL16_HA),
- /* The following are only valid for ppc64. Negative values are
- used instead of a flag. */
- MAP ("higher", - (int) BFD_RELOC_PPC64_HIGHER),
- MAP ("highera", - (int) BFD_RELOC_PPC64_HIGHER_S),
- MAP ("highest", - (int) BFD_RELOC_PPC64_HIGHEST),
- MAP ("highesta", - (int) BFD_RELOC_PPC64_HIGHEST_S),
- MAP ("tocbase", - (int) BFD_RELOC_PPC64_TOC),
- MAP ("toc", - (int) BFD_RELOC_PPC_TOC16),
- MAP ("toc@l", - (int) BFD_RELOC_PPC64_TOC16_LO),
- MAP ("toc@h", - (int) BFD_RELOC_PPC64_TOC16_HI),
- MAP ("toc@ha", - (int) BFD_RELOC_PPC64_TOC16_HA),
- MAP ("dtprel@higher", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHER),
- MAP ("dtprel@highera", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHERA),
- MAP ("dtprel@highest", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHEST),
- MAP ("dtprel@highesta", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHESTA),
- MAP ("tprel@higher", - (int) BFD_RELOC_PPC64_TPREL16_HIGHER),
- MAP ("tprel@highera", - (int) BFD_RELOC_PPC64_TPREL16_HIGHERA),
- MAP ("tprel@highest", - (int) BFD_RELOC_PPC64_TPREL16_HIGHEST),
- MAP ("tprel@highesta", - (int) BFD_RELOC_PPC64_TPREL16_HIGHESTA),
- { (char *) 0, 0, (int) BFD_RELOC_UNUSED }
+ MAP ("l", BFD_RELOC_LO16),
+ MAP ("h", BFD_RELOC_HI16),
+ MAP ("ha", BFD_RELOC_HI16_S),
+ MAP ("brtaken", BFD_RELOC_PPC_B16_BRTAKEN),
+ MAP ("brntaken", BFD_RELOC_PPC_B16_BRNTAKEN),
+ MAP ("got", BFD_RELOC_16_GOTOFF),
+ MAP ("got@l", BFD_RELOC_LO16_GOTOFF),
+ MAP ("got@h", BFD_RELOC_HI16_GOTOFF),
+ MAP ("got@ha", BFD_RELOC_HI16_S_GOTOFF),
+ MAP ("plt@l", BFD_RELOC_LO16_PLTOFF),
+ MAP ("plt@h", BFD_RELOC_HI16_PLTOFF),
+ MAP ("plt@ha", BFD_RELOC_HI16_S_PLTOFF),
+ MAP ("copy", BFD_RELOC_PPC_COPY),
+ MAP ("globdat", BFD_RELOC_PPC_GLOB_DAT),
+ MAP ("sectoff", BFD_RELOC_16_BASEREL),
+ MAP ("sectoff@l", BFD_RELOC_LO16_BASEREL),
+ MAP ("sectoff@h", BFD_RELOC_HI16_BASEREL),
+ MAP ("sectoff@ha", BFD_RELOC_HI16_S_BASEREL),
+ MAP ("tls", BFD_RELOC_PPC_TLS),
+ MAP ("dtpmod", BFD_RELOC_PPC_DTPMOD),
+ MAP ("dtprel", BFD_RELOC_PPC_DTPREL),
+ MAP ("dtprel@l", BFD_RELOC_PPC_DTPREL16_LO),
+ MAP ("dtprel@h", BFD_RELOC_PPC_DTPREL16_HI),
+ MAP ("dtprel@ha", BFD_RELOC_PPC_DTPREL16_HA),
+ MAP ("tprel", BFD_RELOC_PPC_TPREL),
+ MAP ("tprel@l", BFD_RELOC_PPC_TPREL16_LO),
+ MAP ("tprel@h", BFD_RELOC_PPC_TPREL16_HI),
+ MAP ("tprel@ha", BFD_RELOC_PPC_TPREL16_HA),
+ MAP ("got@tlsgd", BFD_RELOC_PPC_GOT_TLSGD16),
+ MAP ("got@tlsgd@l", BFD_RELOC_PPC_GOT_TLSGD16_LO),
+ MAP ("got@tlsgd@h", BFD_RELOC_PPC_GOT_TLSGD16_HI),
+ MAP ("got@tlsgd@ha", BFD_RELOC_PPC_GOT_TLSGD16_HA),
+ MAP ("got@tlsld", BFD_RELOC_PPC_GOT_TLSLD16),
+ MAP ("got@tlsld@l", BFD_RELOC_PPC_GOT_TLSLD16_LO),
+ MAP ("got@tlsld@h", BFD_RELOC_PPC_GOT_TLSLD16_HI),
+ MAP ("got@tlsld@ha", BFD_RELOC_PPC_GOT_TLSLD16_HA),
+ MAP ("got@dtprel", BFD_RELOC_PPC_GOT_DTPREL16),
+ MAP ("got@dtprel@l", BFD_RELOC_PPC_GOT_DTPREL16_LO),
+ MAP ("got@dtprel@h", BFD_RELOC_PPC_GOT_DTPREL16_HI),
+ MAP ("got@dtprel@ha", BFD_RELOC_PPC_GOT_DTPREL16_HA),
+ MAP ("got@tprel", BFD_RELOC_PPC_GOT_TPREL16),
+ MAP ("got@tprel@l", BFD_RELOC_PPC_GOT_TPREL16_LO),
+ MAP ("got@tprel@h", BFD_RELOC_PPC_GOT_TPREL16_HI),
+ MAP ("got@tprel@ha", BFD_RELOC_PPC_GOT_TPREL16_HA),
+ MAP32 ("fixup", BFD_RELOC_CTOR),
+ MAP32 ("plt", BFD_RELOC_24_PLT_PCREL),
+ MAP32 ("pltrel24", BFD_RELOC_24_PLT_PCREL),
+ MAP32 ("local24pc", BFD_RELOC_PPC_LOCAL24PC),
+ MAP32 ("local", BFD_RELOC_PPC_LOCAL24PC),
+ MAP32 ("pltrel", BFD_RELOC_32_PLT_PCREL),
+ MAP32 ("sdarel", BFD_RELOC_GPREL16),
+ MAP32 ("naddr", BFD_RELOC_PPC_EMB_NADDR32),
+ MAP32 ("naddr16", BFD_RELOC_PPC_EMB_NADDR16),
+ MAP32 ("naddr@l", BFD_RELOC_PPC_EMB_NADDR16_LO),
+ MAP32 ("naddr@h", BFD_RELOC_PPC_EMB_NADDR16_HI),
+ MAP32 ("naddr@ha", BFD_RELOC_PPC_EMB_NADDR16_HA),
+ MAP32 ("sdai16", BFD_RELOC_PPC_EMB_SDAI16),
+ MAP32 ("sda2rel", BFD_RELOC_PPC_EMB_SDA2REL),
+ MAP32 ("sda2i16", BFD_RELOC_PPC_EMB_SDA2I16),
+ MAP32 ("sda21", BFD_RELOC_PPC_EMB_SDA21),
+ MAP32 ("mrkref", BFD_RELOC_PPC_EMB_MRKREF),
+ MAP32 ("relsect", BFD_RELOC_PPC_EMB_RELSEC16),
+ MAP32 ("relsect@l", BFD_RELOC_PPC_EMB_RELST_LO),
+ MAP32 ("relsect@h", BFD_RELOC_PPC_EMB_RELST_HI),
+ MAP32 ("relsect@ha", BFD_RELOC_PPC_EMB_RELST_HA),
+ MAP32 ("bitfld", BFD_RELOC_PPC_EMB_BIT_FLD),
+ MAP32 ("relsda", BFD_RELOC_PPC_EMB_RELSDA),
+ MAP32 ("xgot", BFD_RELOC_PPC_TOC16),
+ MAP64 ("higher", BFD_RELOC_PPC64_HIGHER),
+ MAP64 ("highera", BFD_RELOC_PPC64_HIGHER_S),
+ MAP64 ("highest", BFD_RELOC_PPC64_HIGHEST),
+ MAP64 ("highesta", BFD_RELOC_PPC64_HIGHEST_S),
+ MAP64 ("tocbase", BFD_RELOC_PPC64_TOC),
+ MAP64 ("toc", BFD_RELOC_PPC_TOC16),
+ MAP64 ("toc@l", BFD_RELOC_PPC64_TOC16_LO),
+ MAP64 ("toc@h", BFD_RELOC_PPC64_TOC16_HI),
+ MAP64 ("toc@ha", BFD_RELOC_PPC64_TOC16_HA),
+ MAP64 ("dtprel@higher", BFD_RELOC_PPC64_DTPREL16_HIGHER),
+ MAP64 ("dtprel@highera", BFD_RELOC_PPC64_DTPREL16_HIGHERA),
+ MAP64 ("dtprel@highest", BFD_RELOC_PPC64_DTPREL16_HIGHEST),
+ MAP64 ("dtprel@highesta", BFD_RELOC_PPC64_DTPREL16_HIGHESTA),
+ MAP64 ("tprel@higher", BFD_RELOC_PPC64_TPREL16_HIGHER),
+ MAP64 ("tprel@highera", BFD_RELOC_PPC64_TPREL16_HIGHERA),
+ MAP64 ("tprel@highest", BFD_RELOC_PPC64_TPREL16_HIGHEST),
+ MAP64 ("tprel@highesta", BFD_RELOC_PPC64_TPREL16_HIGHESTA),
+ { (char *) 0, 0, 0, 0, BFD_RELOC_UNUSED }
};
if (*str++ != '@')
for (ptr = &mapping[0]; ptr->length > 0; ptr++)
if (ch == ptr->string[0]
&& len == ptr->length
- && memcmp (ident, ptr->string, ptr->length) == 0)
+ && memcmp (ident, ptr->string, ptr->length) == 0
+ && (ppc_obj64 ? ptr->valid64 : ptr->valid32))
{
int reloc = ptr->reloc;
- if (reloc < 0)
- {
- if (!ppc_obj64)
- return BFD_RELOC_UNUSED;
- reloc = -reloc;
- }
-
if (!ppc_obj64)
if (exp_p->X_add_number != 0
&& (reloc == (int) BFD_RELOC_16_GOTOFF
*str_p = str;
if (reloc == (int) BFD_RELOC_PPC64_TOC
- && exp_p->X_op == O_symbol)
+ && exp_p->X_op == O_symbol
+ && strcmp (S_GET_NAME (exp_p->X_add_symbol), ".TOC.") == 0)
{
- /* This reloc type ignores the symbol. Change the symbol
- so that the dummy .TOC. symbol can be omitted from the
- object file. */
+ /* Change the symbol so that the dummy .TOC. symbol can be
+ omitted from the object file. */
exp_p->X_add_symbol = &abs_symbol;
}
ppc_frob_file_before_adjust ()
{
symbolS *symp;
+ asection *toc;
if (!ppc_obj64)
return;
dotname = xmalloc (len + 1);
dotname[0] = '.';
memcpy (dotname + 1, name, len);
- dotsym = symbol_find (dotname);
+ dotsym = symbol_find_noref (dotname, 1);
free (dotname);
if (dotsym != NULL && (symbol_used_p (dotsym)
|| symbol_used_in_reloc_p (dotsym)))
- {
- symbol_mark_used (symp);
- }
+ symbol_mark_used (symp);
+
}
+ toc = bfd_get_section_by_name (stdoutput, ".toc");
+ if (toc != NULL
+ && bfd_section_size (stdoutput, toc) > 0x10000)
+ as_warn (_("TOC section size exceeds 64k"));
+
/* Don't emit .TOC. symbol. */
symp = symbol_find (".TOC.");
if (symp != NULL)
struct ppc_fixup fixups[MAX_INSN_FIXUPS];
int fc;
char *f;
+ int addr_mod;
int i;
#ifdef OBJ_ELF
bfd_reloc_code_real_type reloc;
/* PowerPC operands are just expressions. The only real issue is
that a few operand types are optional. All cases which might use
- an optional operand separate the operands only with commas (in
- some cases parentheses are used, as in ``lwz 1,0(1)'' but such
- cases never have optional operands). There is never more than
- one optional operand for an instruction. So, before we start
- seriously parsing the operands, we check to see if we have an
- optional operand, and, if we do, we count the number of commas to
- see whether the operand should be omitted. */
+ an optional operand separate the operands only with commas (in some
+ cases parentheses are used, as in ``lwz 1,0(1)'' but such cases never
+ have optional operands). Most instructions with optional operands
+ have only one. Those that have more than one optional operand can
+ take either all their operands or none. So, before we start seriously
+ parsing the operands, we check to see if we have optional operands,
+ and if we do, we count the number of commas to see which operands
+ have been omitted. */
skip_optional = 0;
for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
{
/* If there are fewer operands in the line then are called
for by the instruction, we want to skip the optional
- operand. */
+ operands. */
if (opcount < num_operands_expected)
skip_optional = 1;
}
if (ppc_obj64
- && (operand->flags & PPC_OPERAND_DS) != 0)
+ && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
{
switch (reloc)
{
/* Write out the instruction. */
f = frag_more (4);
+ addr_mod = frag_now_fix () & 3;
+ if (frag_now->has_code && frag_now->insn_addr != addr_mod)
+ as_bad (_("instruction address is not a multiple of 4"));
+ frag_now->insn_addr = addr_mod;
+ frag_now->has_code = 1;
md_number_to_chars (f, insn, 4);
#ifdef OBJ_ELF
BFD_RELOC_UNUSED plus the operand index. This lets us easily
handle fixups for any operand type, although that is admittedly
not a very exciting feature. We pick a BFD reloc type in
- md_apply_fix3. */
+ md_apply_fix. */
for (i = 0; i < fc; i++)
{
const struct powerpc_operand *operand;
return SHF_EXCLUDE;
*ptr_msg = _("Bad .section directive: want a,e,w,x,M,S,G,T in string");
- return 0;
+ return -1;
}
int
/* The .comm and .lcomm pseudo-ops for XCOFF. XCOFF puts common
symbols in the .bss segment as though they were local common
- symbols, and uses a different smclas. The native Aix 4.3.3 assember
+ symbols, and uses a different smclas. The native Aix 4.3.3 assembler
aligns .comm and .lcomm to 4 bytes. */
static void
char *name;
char endc;
symbolS *sym;
+ offsetT align;
name = input_line_pointer;
endc = get_symbol_end ();
symbol_get_tc (sym)->class = XMC_PR;
}
- ppc_change_csect (sym);
-
+ align = 2;
if (*input_line_pointer == ',')
{
++input_line_pointer;
- symbol_get_tc (sym)->align = get_absolute_expression ();
+ align = get_absolute_expression ();
}
+ ppc_change_csect (sym, align);
+
demand_empty_rest_of_line ();
}
/* Change to a different csect. */
static void
-ppc_change_csect (sym)
+ppc_change_csect (sym, align)
symbolS *sym;
+ offsetT align;
{
if (S_IS_DEFINED (sym))
subseg_set (S_GET_SEGMENT (sym), symbol_get_tc (sym)->subseg);
int after_toc;
int hold_chunksize;
symbolS *list;
+ int is_code;
+ segT sec;
/* This is a new csect. We need to look at the symbol class to
figure out whether it should go in the text section or the
data section. */
after_toc = 0;
+ is_code = 0;
switch (symbol_get_tc (sym)->class)
{
case XMC_PR:
symbol_get_tc (sym)->subseg = ppc_text_subsegment;
++ppc_text_subsegment;
list_ptr = &ppc_text_csects;
+ is_code = 1;
break;
case XMC_RW:
case XMC_TC0:
hold_chunksize = chunksize;
chunksize = 64;
- subseg_new (segment_name (S_GET_SEGMENT (sym)),
- symbol_get_tc (sym)->subseg);
+ sec = subseg_new (segment_name (S_GET_SEGMENT (sym)),
+ symbol_get_tc (sym)->subseg);
chunksize = hold_chunksize;
if (after_toc)
ppc_after_toc_frag = frag_now;
+ record_alignment (sec, align);
+ if (is_code)
+ frag_align_code (align, 0);
+ else
+ frag_align (align, 0, 0);
+
symbol_set_frag (sym, frag_now);
S_SET_VALUE (sym, (valueT) frag_now_fix ());
- symbol_get_tc (sym)->align = 2;
+ symbol_get_tc (sym)->align = align;
symbol_get_tc (sym)->output = 1;
symbol_get_tc (sym)->within = sym;
sym = symbol_find_or_make (name);
- ppc_change_csect (sym);
+ ppc_change_csect (sym, 2);
demand_empty_rest_of_line ();
}
sym = symbol_find_or_make (real_name);
- ppc_change_csect (sym);
+ ppc_change_csect (sym, 2);
demand_empty_rest_of_line ();
}
/* The .function pseudo-op. This takes several arguments. The first
argument seems to be the external name of the symbol. The second
- argment seems to be the label for the start of the function. gcc
+ argument seems to be the label for the start of the function. gcc
uses the same name for both. I have no idea what the third and
fourth arguments are meant to be. The optional fifth argument is
an expression for the size of the function. In COFF this symbol
give to this location in the toc; this will be a symbol with class
TC. The rest of the arguments are N-byte values to actually put at
this location in the TOC; often there is just one more argument, a
- relocateable symbol reference. The size of the value to store
+ relocatable symbol reference. The size of the value to store
depends on target word size. A 32-bit target uses 4-byte values, a
64-bit target uses 8-byte values.
}
/* Pseudo-op .machine. */
-/* FIXME: `.machine' is a nop for the moment. It would be nice to
- accept this directive on the first line of input and set ppc_obj64
- and the target format accordingly. Unfortunately, the target
- format is selected in output-file.c:output_file_create before we
- even get to md_begin, so it's not possible without changing
- as.c:main. */
static void
ppc_machine (ignore)
int ignore ATTRIBUTE_UNUSED;
{
- discard_rest_of_line ();
+ char *cpu_string;
+#define MAX_HISTORY 100
+ static unsigned long *cpu_history;
+ static int curr_hist;
+
+ 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;
+ }
+
+ if (cpu_string != NULL)
+ {
+ unsigned long old_cpu = ppc_cpu;
+ char *p;
+
+ for (p = cpu_string; *p != 0; p++)
+ *p = TOLOWER (*p);
+
+ if (strcmp (cpu_string, "push") == 0)
+ {
+ if (cpu_history == NULL)
+ cpu_history = xmalloc (MAX_HISTORY * sizeof (*cpu_history));
+
+ if (curr_hist >= MAX_HISTORY)
+ as_bad (_(".machine stack overflow"));
+ else
+ cpu_history[curr_hist++] = ppc_cpu;
+ }
+ else if (strcmp (cpu_string, "pop") == 0)
+ {
+ if (curr_hist <= 0)
+ as_bad (_(".machine stack underflow"));
+ else
+ ppc_cpu = cpu_history[--curr_hist];
+ }
+ else if (parse_cpu (cpu_string))
+ ;
+ else
+ as_bad (_("invalid machine `%s'"), cpu_string);
+
+ if (ppc_cpu != old_cpu)
+ ppc_setup_opcodes ();
+ }
+
+ demand_empty_rest_of_line ();
}
/* See whether a symbol is in the TOC section. */
{
S_SET_VALUE (symbolP, (valueT) temp);
S_SET_EXTERNAL (symbolP);
+ S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
}
demand_empty_rest_of_line ();
&symbol_rootP, &symbol_lastP);
symbol_get_tc (ppc_current_csect)->within = sym;
}
+
+#ifdef OBJ_ELF
+ dwarf2_emit_label (sym);
+#endif
}
/* This variable is set by ppc_frob_symbol if any absolute symbols are
table. */
if (! symbol_used_in_reloc_p (sym)
&& ((symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM) != 0
- || (! S_IS_EXTERNAL (sym)
+ || (! (S_IS_EXTERNAL (sym) || S_IS_WEAK (sym))
&& ! symbol_get_tc (sym)->output
&& S_GET_STORAGE_CLASS (sym) != C_FILE)))
return 1;
}
}
- if (! S_IS_EXTERNAL (sym)
+ if (! (S_IS_EXTERNAL (sym) || S_IS_WEAK (sym))
&& (symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM) == 0
&& S_GET_STORAGE_CLASS (sym) != C_FILE
&& S_GET_STORAGE_CLASS (sym) != C_FCN
ppc_frob_section (sec)
asection *sec;
{
- static bfd_size_type vma = 0;
+ static bfd_vma vma = 0;
+ vma = md_section_align (sec, vma);
bfd_set_section_vma (stdoutput, sec, vma);
vma += bfd_section_size (stdoutput, sec);
}
case BFD_RELOC_PPC_B16_BRNTAKEN:
case BFD_RELOC_PPC_BA16_BRTAKEN:
case BFD_RELOC_PPC_BA16_BRNTAKEN:
+ case BFD_RELOC_24_PLT_PCREL:
case BFD_RELOC_PPC64_TOC:
return 1;
default:
&& fix->fx_r_type != BFD_RELOC_VTABLE_INHERIT
&& fix->fx_r_type != BFD_RELOC_VTABLE_ENTRY
&& !(fix->fx_r_type >= BFD_RELOC_PPC_TLS
- && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA)
- && (fix->fx_pcrel
- || (fix->fx_subsy != NULL
- && (S_GET_SEGMENT (fix->fx_subsy)
- == S_GET_SEGMENT (fix->fx_addsy)))
- || S_IS_LOCAL (fix->fx_addsy)));
+ && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA));
}
#endif
fixup. */
void
-md_apply_fix3 (fixP, valP, seg)
+md_apply_fix (fixP, valP, seg)
fixS *fixP;
valueT * valP;
segT seg ATTRIBUTE_UNUSED;
fixP->fx_done = 1;
#else
/* FIXME FIXME FIXME: The value we are passed in *valP includes
- the symbol values. Since we are using BFD_ASSEMBLER, if we are
- doing this relocation the code in write.c is going to call
- bfd_install_relocation, which is also going to use the symbol
- value. That means that if the reloc is fully resolved we want to
- use *valP since bfd_install_relocation is not being used.
+ the symbol values. If we are doing this relocation the code in
+ write.c is going to call bfd_install_relocation, which is also
+ going to use the symbol value. That means that if the reloc is
+ fully resolved we want to use *valP since bfd_install_relocation is
+ not being used.
However, if the reloc is not fully resolved we do not want to use
*valP, and must use fx_offset instead. However, if the reloc
is PC relative, we do want to use *valP since it includes the
value, 8);
break;
- case BFD_RELOC_LO16:
- case BFD_RELOC_16:
case BFD_RELOC_GPREL16:
case BFD_RELOC_16_GOT_PCREL:
case BFD_RELOC_16_GOTOFF:
value, 2);
break;
+ case BFD_RELOC_16:
+ if (fixP->fx_pcrel)
+ fixP->fx_r_type = BFD_RELOC_16_PCREL;
+ /* fall through */
+
+ case BFD_RELOC_16_PCREL:
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
+ value, 2);
+ break;
+
+ case BFD_RELOC_LO16:
+ if (fixP->fx_pcrel)
+ fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
+ /* fall through */
+
+ case BFD_RELOC_LO16_PCREL:
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
+ value, 2);
+ break;
+
/* This case happens when you write, for example,
lis %r3,(L1-L2)@ha
where L1 and L2 are defined later. */
case BFD_RELOC_HI16:
if (fixP->fx_pcrel)
- abort ();
+ fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
+ /* fall through */
+
+ case BFD_RELOC_HI16_PCREL:
md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
PPC_HI (value), 2);
break;
case BFD_RELOC_HI16_S:
if (fixP->fx_pcrel)
- abort ();
+ fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
+ /* fall through */
+
+ case BFD_RELOC_HI16_S_PCREL:
md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
PPC_HA (value), 2);
break;
if (fixP->fx_pcrel)
abort ();
{
- unsigned char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
- unsigned long val;
+ char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
+ unsigned long val, mask;
if (target_big_endian)
- val = bfd_getb16 (where);
+ val = bfd_getb32 (where - 2);
else
- val = bfd_getl16 (where);
- val |= (value & 0xfffc);
+ val = bfd_getl32 (where);
+ mask = 0xfffc;
+ /* lq insns reserve the four lsbs. */
+ if ((ppc_cpu & PPC_OPCODE_POWER4) != 0
+ && (val & (0x3f << 26)) == (56u << 26))
+ mask = 0xfff0;
+ val |= value & mask;
if (target_big_endian)
bfd_putb16 ((bfd_vma) val, where);
else
}
break;
+ case BFD_RELOC_PPC_B16_BRTAKEN:
+ case BFD_RELOC_PPC_B16_BRNTAKEN:
+ case BFD_RELOC_PPC_BA16_BRTAKEN:
+ case BFD_RELOC_PPC_BA16_BRNTAKEN:
+ break;
+
case BFD_RELOC_PPC_TLS:
+ break;
+
case BFD_RELOC_PPC_DTPMOD:
case BFD_RELOC_PPC_TPREL16:
case BFD_RELOC_PPC_TPREL16_LO:
case BFD_RELOC_PPC64_DTPREL16_HIGHERA:
case BFD_RELOC_PPC64_DTPREL16_HIGHEST:
case BFD_RELOC_PPC64_DTPREL16_HIGHESTA:
+ S_SET_THREAD_LOCAL (fixP->fx_addsy);
break;
#endif
/* Because SDA21 modifies the register field, the size is set to 4
case BFD_RELOC_8:
if (fixP->fx_pcrel)
- abort ();
-
- md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
- value, 1);
+ {
+ /* This can occur if there is a bug in the input assembler, eg:
+ ".byte <undefined_symbol> - ." */
+ if (fixP->fx_addsy)
+ as_bad (_("Unable to handle reference to symbol %s"),
+ S_GET_NAME (fixP->fx_addsy));
+ else
+ as_bad (_("Unable to resolve expression"));
+ fixP->fx_done = 1;
+ }
+ else
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
+ value, 1);
break;
case BFD_RELOC_24_PLT_PCREL:
#ifdef OBJ_ELF
fixP->fx_addnumber = value;
+
+ /* PowerPC uses RELA relocs, ie. the reloc addend is stored separately
+ from the section contents. If we are going to be emitting a reloc
+ then the section contents are immaterial, so don't warn if they
+ happen to overflow. Leave such warnings to ld. */
+ if (!fixP->fx_done)
+ fixP->fx_no_overflow = 1;
#else
if (fixP->fx_r_type != BFD_RELOC_PPC_TOC16)
fixP->fx_addnumber = 0;
return reloc;
}
+
+void
+ppc_cfi_frame_initial_instructions ()
+{
+ cfi_add_CFA_def_cfa (1, 0);
+}
+
+int
+tc_ppc_regname_to_dw2regnum (const char *regname)
+{
+ unsigned int regnum = -1;
+ unsigned int i;
+ const char *p;
+ char *q;
+ static struct { char *name; int dw2regnum; } regnames[] =
+ {
+ { "sp", 1 }, { "r.sp", 1 }, { "rtoc", 2 }, { "r.toc", 2 },
+ { "mq", 64 }, { "lr", 65 }, { "ctr", 66 }, { "ap", 67 },
+ { "cr", 70 }, { "xer", 76 }, { "vrsave", 109 }, { "vscr", 110 },
+ { "spe_acc", 111 }, { "spefscr", 112 }
+ };
+
+ for (i = 0; i < ARRAY_SIZE (regnames); ++i)
+ if (strcmp (regnames[i].name, regname) == 0)
+ return regnames[i].dw2regnum;
+
+ if (regname[0] == 'r' || regname[0] == 'f' || regname[0] == 'v')
+ {
+ p = regname + 1 + (regname[1] == '.');
+ regnum = strtoul (p, &q, 10);
+ if (p == q || *q || regnum >= 32)
+ return -1;
+ if (regname[0] == 'f')
+ regnum += 32;
+ else if (regname[0] == 'v')
+ regnum += 77;
+ }
+ else if (regname[0] == 'c' && regname[1] == 'r')
+ {
+ p = regname + 2 + (regname[2] == '.');
+ if (p[0] < '0' || p[0] > '7' || p[1])
+ return -1;
+ regnum = p[0] - '0' + 68;
+ }
+ return regnum;
+}