/* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of GAS, the GNU Assembler.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
+ the Free Software Foundation; either version 3, or (at your option)
any later version.
GAS is distributed in the hope that it will be useful,
static bfd_boolean reg_names_p = TARGET_REG_NAMES_P;
-static bfd_boolean register_name PARAMS ((expressionS *));
-static void ppc_set_cpu PARAMS ((void));
-static void ppc_macro PARAMS ((char *str, const struct powerpc_macro *macro));
-static void ppc_byte PARAMS ((int));
+static void ppc_macro (char *, const struct powerpc_macro *);
+static void ppc_byte (int);
#if defined (OBJ_XCOFF) || defined (OBJ_ELF)
-static int ppc_is_toc_sym PARAMS ((symbolS *sym));
-static void ppc_tc PARAMS ((int));
-static void ppc_machine PARAMS ((int));
+static void ppc_tc (int);
+static void ppc_machine (int);
#endif
#ifdef OBJ_XCOFF
-static void ppc_comm PARAMS ((int));
-static void ppc_bb PARAMS ((int));
-static void ppc_bc PARAMS ((int));
-static void ppc_bf PARAMS ((int));
-static void ppc_biei PARAMS ((int));
-static void ppc_bs PARAMS ((int));
-static void ppc_eb PARAMS ((int));
-static void ppc_ec PARAMS ((int));
-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 *, offsetT));
-static void ppc_function PARAMS ((int));
-static void ppc_extern PARAMS ((int));
-static void ppc_lglobl PARAMS ((int));
-static void ppc_section PARAMS ((int));
-static void ppc_named_section PARAMS ((int));
-static void ppc_stabx PARAMS ((int));
-static void ppc_rename PARAMS ((int));
-static void ppc_toc PARAMS ((int));
-static void ppc_xcoff_cons PARAMS ((int));
-static void ppc_vbyte PARAMS ((int));
+static void ppc_comm (int);
+static void ppc_bb (int);
+static void ppc_bc (int);
+static void ppc_bf (int);
+static void ppc_biei (int);
+static void ppc_bs (int);
+static void ppc_eb (int);
+static void ppc_ec (int);
+static void ppc_ef (int);
+static void ppc_es (int);
+static void ppc_csect (int);
+static void ppc_change_csect (symbolS *, offsetT);
+static void ppc_function (int);
+static void ppc_extern (int);
+static void ppc_lglobl (int);
+static void ppc_section (int);
+static void ppc_named_section (int);
+static void ppc_stabx (int);
+static void ppc_rename (int);
+static void ppc_toc (int);
+static void ppc_xcoff_cons (int);
+static void ppc_vbyte (int);
#endif
#ifdef OBJ_ELF
-static bfd_reloc_code_real_type ppc_elf_suffix PARAMS ((char **, expressionS *));
-static void ppc_elf_cons PARAMS ((int));
-static void ppc_elf_rdata PARAMS ((int));
-static void ppc_elf_lcomm PARAMS ((int));
-static void ppc_elf_validate_fix PARAMS ((fixS *, segT));
-static void ppc_apuinfo_section_add PARAMS ((unsigned int apu, unsigned int version));
+static void ppc_elf_cons (int);
+static void ppc_elf_rdata (int);
+static void ppc_elf_lcomm (int);
#endif
#ifdef TE_PE
-static void ppc_set_current_section PARAMS ((segT));
-static void ppc_previous PARAMS ((int));
-static void ppc_pdata PARAMS ((int));
-static void ppc_ydata PARAMS ((int));
-static void ppc_reldata PARAMS ((int));
-static void ppc_rdata PARAMS ((int));
-static void ppc_ualong PARAMS ((int));
-static void ppc_znop PARAMS ((int));
-static void ppc_pe_comm PARAMS ((int));
-static void ppc_pe_section PARAMS ((int));
-static void ppc_pe_function PARAMS ((int));
-static void ppc_pe_tocd PARAMS ((int));
+static void ppc_previous (int);
+static void ppc_pdata (int);
+static void ppc_ydata (int);
+static void ppc_reldata (int);
+static void ppc_rdata (int);
+static void ppc_ualong (int);
+static void ppc_znop (int);
+static void ppc_pe_comm (int);
+static void ppc_pe_section (int);
+static void ppc_pe_function (int);
+static void ppc_pe_tocd (int);
#endif
\f
/* Generic assembler global variables which must be defined by all
/* The dwarf2 data alignment, adjusted for 32 or 64 bit. */
int ppc_cie_data_alignment;
+
+/* The type of processor we are assembling for. This is one or more
+ of the PPC_OPCODE flags defined in opcode/ppc.h. */
+ppc_cpu_t ppc_cpu = 0;
\f
/* The target specific pseudo-ops which we support. */
{ "f.3", 3 },
{ "f.30", 30 },
{ "f.31", 31 },
+
+ { "f.32", 32 }, /* Extended floating point scalar registers (ISA 2.06). */
+ { "f.33", 33 },
+ { "f.34", 34 },
+ { "f.35", 35 },
+ { "f.36", 36 },
+ { "f.37", 37 },
+ { "f.38", 38 },
+ { "f.39", 39 },
{ "f.4", 4 },
+ { "f.40", 40 },
+ { "f.41", 41 },
+ { "f.42", 42 },
+ { "f.43", 43 },
+ { "f.44", 44 },
+ { "f.45", 45 },
+ { "f.46", 46 },
+ { "f.47", 47 },
+ { "f.48", 48 },
+ { "f.49", 49 },
{ "f.5", 5 },
+ { "f.50", 50 },
+ { "f.51", 51 },
+ { "f.52", 52 },
+ { "f.53", 53 },
+ { "f.54", 54 },
+ { "f.55", 55 },
+ { "f.56", 56 },
+ { "f.57", 57 },
+ { "f.58", 58 },
+ { "f.59", 59 },
{ "f.6", 6 },
+ { "f.60", 60 },
+ { "f.61", 61 },
+ { "f.62", 62 },
+ { "f.63", 63 },
{ "f.7", 7 },
{ "f.8", 8 },
{ "f.9", 9 },
{ "f3", 3 },
{ "f30", 30 },
{ "f31", 31 },
+
+ { "f32", 32 }, /* Extended floating point scalar registers (ISA 2.06). */
+ { "f33", 33 },
+ { "f34", 34 },
+ { "f35", 35 },
+ { "f36", 36 },
+ { "f37", 37 },
+ { "f38", 38 },
+ { "f39", 39 },
{ "f4", 4 },
+ { "f40", 40 },
+ { "f41", 41 },
+ { "f42", 42 },
+ { "f43", 43 },
+ { "f44", 44 },
+ { "f45", 45 },
+ { "f46", 46 },
+ { "f47", 47 },
+ { "f48", 48 },
+ { "f49", 49 },
{ "f5", 5 },
+ { "f50", 50 },
+ { "f51", 51 },
+ { "f52", 52 },
+ { "f53", 53 },
+ { "f54", 54 },
+ { "f55", 55 },
+ { "f56", 56 },
+ { "f57", 57 },
+ { "f58", 58 },
+ { "f59", 59 },
{ "f6", 6 },
+ { "f60", 60 },
+ { "f61", 61 },
+ { "f62", 62 },
+ { "f63", 63 },
{ "f7", 7 },
{ "f8", 8 },
{ "f9", 9 },
{ "fpscr", 0 },
+ /* Quantization registers used with pair single instructions. */
+ { "gqr.0", 0 },
+ { "gqr.1", 1 },
+ { "gqr.2", 2 },
+ { "gqr.3", 3 },
+ { "gqr.4", 4 },
+ { "gqr.5", 5 },
+ { "gqr.6", 6 },
+ { "gqr.7", 7 },
+ { "gqr0", 0 },
+ { "gqr1", 1 },
+ { "gqr2", 2 },
+ { "gqr3", 3 },
+ { "gqr4", 4 },
+ { "gqr5", 5 },
+ { "gqr6", 6 },
+ { "gqr7", 7 },
+
{ "lr", 8 }, /* Link Register */
{ "pmr", 0 },
{ "srr0", 26 }, /* Machine Status Save/Restore Register 0 */
{ "srr1", 27 }, /* Machine Status Save/Restore Register 1 */
- { "v.0", 0 }, /* Vector registers */
+ { "v.0", 0 }, /* Vector (Altivec/VMX) registers */
{ "v.1", 1 },
{ "v.10", 10 },
{ "v.11", 11 },
{ "v8", 8 },
{ "v9", 9 },
+ { "vs.0", 0 }, /* Vector Scalar (VSX) registers (ISA 2.06). */
+ { "vs.1", 1 },
+ { "vs.10", 10 },
+ { "vs.11", 11 },
+ { "vs.12", 12 },
+ { "vs.13", 13 },
+ { "vs.14", 14 },
+ { "vs.15", 15 },
+ { "vs.16", 16 },
+ { "vs.17", 17 },
+ { "vs.18", 18 },
+ { "vs.19", 19 },
+ { "vs.2", 2 },
+ { "vs.20", 20 },
+ { "vs.21", 21 },
+ { "vs.22", 22 },
+ { "vs.23", 23 },
+ { "vs.24", 24 },
+ { "vs.25", 25 },
+ { "vs.26", 26 },
+ { "vs.27", 27 },
+ { "vs.28", 28 },
+ { "vs.29", 29 },
+ { "vs.3", 3 },
+ { "vs.30", 30 },
+ { "vs.31", 31 },
+ { "vs.32", 32 },
+ { "vs.33", 33 },
+ { "vs.34", 34 },
+ { "vs.35", 35 },
+ { "vs.36", 36 },
+ { "vs.37", 37 },
+ { "vs.38", 38 },
+ { "vs.39", 39 },
+ { "vs.4", 4 },
+ { "vs.40", 40 },
+ { "vs.41", 41 },
+ { "vs.42", 42 },
+ { "vs.43", 43 },
+ { "vs.44", 44 },
+ { "vs.45", 45 },
+ { "vs.46", 46 },
+ { "vs.47", 47 },
+ { "vs.48", 48 },
+ { "vs.49", 49 },
+ { "vs.5", 5 },
+ { "vs.50", 50 },
+ { "vs.51", 51 },
+ { "vs.52", 52 },
+ { "vs.53", 53 },
+ { "vs.54", 54 },
+ { "vs.55", 55 },
+ { "vs.56", 56 },
+ { "vs.57", 57 },
+ { "vs.58", 58 },
+ { "vs.59", 59 },
+ { "vs.6", 6 },
+ { "vs.60", 60 },
+ { "vs.61", 61 },
+ { "vs.62", 62 },
+ { "vs.63", 63 },
+ { "vs.7", 7 },
+ { "vs.8", 8 },
+ { "vs.9", 9 },
+
+ { "vs0", 0 },
+ { "vs1", 1 },
+ { "vs10", 10 },
+ { "vs11", 11 },
+ { "vs12", 12 },
+ { "vs13", 13 },
+ { "vs14", 14 },
+ { "vs15", 15 },
+ { "vs16", 16 },
+ { "vs17", 17 },
+ { "vs18", 18 },
+ { "vs19", 19 },
+ { "vs2", 2 },
+ { "vs20", 20 },
+ { "vs21", 21 },
+ { "vs22", 22 },
+ { "vs23", 23 },
+ { "vs24", 24 },
+ { "vs25", 25 },
+ { "vs26", 26 },
+ { "vs27", 27 },
+ { "vs28", 28 },
+ { "vs29", 29 },
+ { "vs3", 3 },
+ { "vs30", 30 },
+ { "vs31", 31 },
+ { "vs32", 32 },
+ { "vs33", 33 },
+ { "vs34", 34 },
+ { "vs35", 35 },
+ { "vs36", 36 },
+ { "vs37", 37 },
+ { "vs38", 38 },
+ { "vs39", 39 },
+ { "vs4", 4 },
+ { "vs40", 40 },
+ { "vs41", 41 },
+ { "vs42", 42 },
+ { "vs43", 43 },
+ { "vs44", 44 },
+ { "vs45", 45 },
+ { "vs46", 46 },
+ { "vs47", 47 },
+ { "vs48", 48 },
+ { "vs49", 49 },
+ { "vs5", 5 },
+ { "vs50", 50 },
+ { "vs51", 51 },
+ { "vs52", 52 },
+ { "vs53", 53 },
+ { "vs54", 54 },
+ { "vs55", 55 },
+ { "vs56", 56 },
+ { "vs57", 57 },
+ { "vs58", 58 },
+ { "vs59", 59 },
+ { "vs6", 6 },
+ { "vs60", 60 },
+ { "vs61", 61 },
+ { "vs62", 62 },
+ { "vs63", 63 },
+ { "vs7", 7 },
+ { "vs8", 8 },
+ { "vs9", 9 },
+
{ "xer", 1 },
};
/* Given NAME, find the register number associated with that name, return
the integer value associated with the given name or -1 on failure. */
-static int reg_name_search
- PARAMS ((const struct pd_reg *, int, const char * name));
-
static int
-reg_name_search (regs, regcount, name)
- const struct pd_reg *regs;
- int regcount;
- const char *name;
+reg_name_search (const struct pd_reg *regs, int regcount, const char *name)
{
int middle, low, high;
int cmp;
*/
static bfd_boolean
-register_name (expressionP)
- expressionS *expressionP;
+register_name (expressionS *expressionP)
{
int reg_number;
char *name;
expression. */
int
-ppc_parse_name (name, expr)
- const char *name;
- expressionS *expr;
+ppc_parse_name (const char *name, expressionS *exp)
{
int val;
if (! cr_operand)
return 0;
+ if (*name == '%')
+ ++name;
val = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0],
name);
if (val < 0)
return 0;
- expr->X_op = O_constant;
- expr->X_add_number = val;
+ exp->X_op = O_constant;
+ exp->X_add_number = val;
return 1;
}
\f
/* Local variables. */
-/* The type of processor we are assembling for. This is one or more
- of the PPC_OPCODE flags defined in opcode/ppc.h. */
-static unsigned long ppc_cpu = 0;
-
/* Whether to target xcoff64/elf64. */
static unsigned int ppc_obj64 = BFD_DEFAULT_TARGET_SIZE == 64;
};
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);
- }
- else if (strcmp (arg, "power6") == 0)
- {
- ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
- | PPC_OPCODE_64 | PPC_OPCODE_POWER4
- | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6);
- }
- else if (strcmp (arg, "cell") == 0)
- {
- ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
- | PPC_OPCODE_64 | PPC_OPCODE_POWER4
- | PPC_OPCODE_CELL);
- }
- /* -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;
- char *arg;
+md_parse_option (int c, char *arg)
{
+ ppc_cpu_t new_cpu;
+
switch (c)
{
case 'u':
break;
case 'm':
- if (parse_cpu (arg))
- ;
+ if ((new_cpu = ppc_parse_cpu (ppc_cpu, arg)) != 0)
+ ppc_cpu = new_cpu;
else if (strcmp (arg, "regnames") == 0)
reg_names_p = TRUE;
}
void
-md_show_usage (stream)
- FILE *stream;
+md_show_usage (FILE *stream)
{
fprintf (stream, _("\
PowerPC options:\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 generate code for PowerPC 403\n\
+-m405 generate code for PowerPC 405\n\
-m440 generate code for PowerPC 440\n\
+-m464 generate code for PowerPC 464\n\
+-m476 generate code for PowerPC 476\n\
-m7400, -m7410, -m7450, -m7455\n\
- generate code For PowerPC 7400/7410/7450/7455\n"));
+ generate code for PowerPC 7400/7410/7450/7455\n\
+-m750cl generate code for PowerPC 750cl\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\
+-mbooke generate code for 32-bit PowerPC BookE\n\
+-ma2 generate code for A2 architecture\n\
-mpower4 generate code for Power4 architecture\n\
-mpower5 generate code for Power5 architecture\n\
-mpower6 generate code for Power6 architecture\n\
+-mpower7 generate code for Power7 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"));
fprintf (stream, _("\
-maltivec generate code for AltiVec\n\
+-mvsx generate code for Vector-Scalar (VSX) instructions\n\
-me300 generate code for PowerPC e300 family\n\
-me500, -me500x2 generate code for Motorola e500 core complex\n\
+-me500mc, generate code for Freescale e500mc core complex\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"));
/* Set ppc_cpu if it is not already set. */
static void
-ppc_set_cpu ()
+ppc_set_cpu (void)
{
const char *default_os = TARGET_OS;
const char *default_cpu = TARGET_CPU;
are called well before md_begin, when the output file is opened. */
enum bfd_architecture
-ppc_arch ()
+ppc_arch (void)
{
const char *default_cpu = TARGET_CPU;
ppc_set_cpu ();
}
unsigned long
-ppc_mach ()
+ppc_mach (void)
{
if (ppc_obj64)
return bfd_mach_ppc64;
}
extern char*
-ppc_target_format ()
+ppc_target_format (void)
{
#ifdef OBJ_COFF
#ifdef TE_PE
static void
ppc_setup_opcodes (void)
{
- register const struct powerpc_opcode *op;
+ const struct powerpc_opcode *op;
const struct powerpc_opcode *op_end;
const struct powerpc_macro *macro;
const struct powerpc_macro *macro_end;
const unsigned char *o;
unsigned long omask = op->mask;
+ if (op != powerpc_opcodes)
+ {
+ /* The major opcodes had better be sorted. Code in the
+ disassembler assumes the insns are sorted according to
+ major opcode. */
+ if (PPC_OP (op[0].opcode) < PPC_OP (op[-1].opcode))
+ {
+ as_bad (_("major opcode is not sorted for %s"),
+ op->name);
+ bad_insn = TRUE;
+ }
+
+ /* Warn if the table isn't more strictly ordered.
+ Unfortunately it doesn't seem possible to order the
+ table on much more than the major opcode, which makes
+ it difficult to implement a binary search in the
+ disassembler. The problem is that we have multiple
+ ways to disassemble instructions, and we usually want
+ to choose a more specific form (with more bits set in
+ the opcode) than a more general form. eg. all of the
+ following are equivalent:
+ bne label # opcode = 0x40820000, mask = 0xff830003
+ bf 2,label # opcode = 0x40800000, mask = 0xff800003
+ bc 4,2,label # opcode = 0x40000000, mask = 0xfc000003
+
+ There are also cases where the table needs to be out
+ of order to disassemble the correct instruction for
+ processor variants. */
+ else if (0)
+ {
+ unsigned long t1 = op[0].opcode;
+ unsigned long t2 = op[-1].opcode;
+
+ if (((t1 ^ t2) & 0xfc0007ff) == 0
+ && (t1 & 0xfc0006df) == 0x7c000286)
+ {
+ /* spr field is split. */
+ t1 = ((t1 & ~0x1ff800)
+ | ((t1 & 0xf800) << 5) | ((t1 & 0x1f0000) >> 5));
+ t2 = ((t2 & ~0x1ff800)
+ | ((t2 & 0xf800) << 5) | ((t2 & 0x1f0000) >> 5));
+ }
+ if (t1 < t2)
+ as_warn (_("%s (%08lx %08lx) after %s (%08lx %08lx)"),
+ op[0].name, op[0].opcode, op[0].mask,
+ op[-1].name, op[-1].opcode, op[-1].mask);
+ }
+ }
+
/* The mask had better not trim off opcode bits. */
if ((op->opcode & omask) != op->opcode)
{
|| ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64))
== (ppc_cpu & (PPC_OPCODE_32 | PPC_OPCODE_64)))
|| (ppc_cpu & PPC_OPCODE_64_BRIDGE) != 0)
- /* Certain instructions (eg: extsw) do not exist in the
- 32-bit BookE instruction set, but they do exist in the
- 64-bit BookE instruction set, and other PPC instruction
- sets. Check to see if the opcode has the BOOKE64 flag set.
- If it does make sure that the target CPU is not the BookE32. */
- && ((op->flags & PPC_OPCODE_BOOKE64) == 0
- || (ppc_cpu & PPC_OPCODE_BOOKE64) == PPC_OPCODE_BOOKE64
- || (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)))
- && ((op->flags & PPC_OPCODE_POWER5) == 0
- || ((op->flags & PPC_OPCODE_POWER5)
- == (ppc_cpu & PPC_OPCODE_POWER5)))
- && ((op->flags & PPC_OPCODE_POWER6) == 0
- || ((op->flags & PPC_OPCODE_POWER6)
- == (ppc_cpu & PPC_OPCODE_POWER6))))
+ && !(ppc_cpu & op->deprecated))
{
const char *retval;
- retval = hash_insert (ppc_hash, op->name, (PTR) op);
+ retval = hash_insert (ppc_hash, op->name, (void *) op);
if (retval != NULL)
{
/* Ignore Power duplicates for -m601. */
if ((ppc_cpu & PPC_OPCODE_ANY) != 0)
for (op = powerpc_opcodes; op < op_end; op++)
- hash_insert (ppc_hash, op->name, (PTR) op);
+ hash_insert (ppc_hash, op->name, (void *) op);
/* Insert the macros into a hash table. */
ppc_macro_hash = hash_new ();
{
const char *retval;
- retval = hash_insert (ppc_macro_hash, macro->name, (PTR) macro);
+ retval = hash_insert (ppc_macro_hash, macro->name, (void *) macro);
if (retval != (const char *) NULL)
{
as_bad (_("duplicate macro %s"), macro->name);
opened. */
void
-md_begin ()
+md_begin (void)
{
ppc_set_cpu ();
}
void
-ppc_cleanup ()
+ppc_cleanup (void)
{
#ifdef OBJ_ELF
if (ppc_apuinfo_list == NULL)
ppc_insert_operand (unsigned long insn,
const struct powerpc_operand *operand,
offsetT val,
+ ppc_cpu_t cpu,
char *file,
unsigned int line)
{
const char *errmsg;
errmsg = NULL;
- insn = (*operand->insert) (insn, (long) val, ppc_cpu, &errmsg);
+ insn = (*operand->insert) (insn, (long) val, cpu, &errmsg);
if (errmsg != (const char *) NULL)
- as_bad_where (file, line, errmsg);
+ as_bad_where (file, line, "%s", errmsg);
}
else
insn |= ((long) val & operand->bitm) << operand->shift;
#ifdef OBJ_ELF
/* Parse @got, etc. and return the desired relocation. */
static bfd_reloc_code_real_type
-ppc_elf_suffix (str_p, exp_p)
- char **str_p;
- expressionS *exp_p;
+ppc_elf_suffix (char **str_p, expressionS *exp_p)
{
struct map_bfd {
char *string;
{
int reloc = ptr->reloc;
- if (!ppc_obj64)
- if (exp_p->X_add_number != 0
- && (reloc == (int) BFD_RELOC_16_GOTOFF
- || reloc == (int) BFD_RELOC_LO16_GOTOFF
- || reloc == (int) BFD_RELOC_HI16_GOTOFF
- || reloc == (int) BFD_RELOC_HI16_S_GOTOFF))
- as_warn (_("identifier+constant@got means identifier@got+constant"));
+ if (!ppc_obj64 && exp_p->X_add_number != 0)
+ {
+ switch (reloc)
+ {
+ case BFD_RELOC_16_GOTOFF:
+ case BFD_RELOC_LO16_GOTOFF:
+ case BFD_RELOC_HI16_GOTOFF:
+ case BFD_RELOC_HI16_S_GOTOFF:
+ as_warn (_("identifier+constant@got means "
+ "identifier@got+constant"));
+ break;
+
+ case BFD_RELOC_PPC_GOT_TLSGD16:
+ case BFD_RELOC_PPC_GOT_TLSGD16_LO:
+ case BFD_RELOC_PPC_GOT_TLSGD16_HI:
+ case BFD_RELOC_PPC_GOT_TLSGD16_HA:
+ case BFD_RELOC_PPC_GOT_TLSLD16:
+ case BFD_RELOC_PPC_GOT_TLSLD16_LO:
+ case BFD_RELOC_PPC_GOT_TLSLD16_HI:
+ case BFD_RELOC_PPC_GOT_TLSLD16_HA:
+ case BFD_RELOC_PPC_GOT_DTPREL16:
+ case BFD_RELOC_PPC_GOT_DTPREL16_LO:
+ case BFD_RELOC_PPC_GOT_DTPREL16_HI:
+ case BFD_RELOC_PPC_GOT_DTPREL16_HA:
+ case BFD_RELOC_PPC_GOT_TPREL16:
+ case BFD_RELOC_PPC_GOT_TPREL16_LO:
+ case BFD_RELOC_PPC_GOT_TPREL16_HI:
+ case BFD_RELOC_PPC_GOT_TPREL16_HA:
+ as_bad (_("symbol+offset not supported for got tls"));
+ break;
+ }
+ }
/* Now check for identifier@suffix+constant. */
if (*str == '-' || *str == '+')
/* Like normal .long/.short/.word, except support @got, etc.
Clobbers input_line_pointer, checks end-of-line. */
static void
-ppc_elf_cons (nbytes)
- register int nbytes; /* 1=.byte, 2=.word, 4=.long, 8=.llong. */
+ppc_elf_cons (int nbytes /* 1=.byte, 2=.word, 4=.long, 8=.llong */)
{
expressionS exp;
bfd_reloc_code_real_type reloc;
/* Solaris pseduo op to change to the .rodata section. */
static void
-ppc_elf_rdata (xxx)
- int xxx;
+ppc_elf_rdata (int xxx)
{
char *save_line = input_line_pointer;
static char section[] = ".rodata\n";
/* Pseudo op to make file scope bss items. */
static void
-ppc_elf_lcomm (xxx)
- int xxx ATTRIBUTE_UNUSED;
+ppc_elf_lcomm (int xxx ATTRIBUTE_UNUSED)
{
- register char *name;
- register char c;
- register char *p;
+ char *name;
+ char c;
+ char *p;
offsetT size;
- register symbolS *symbolP;
+ symbolS *symbolP;
offsetT align;
segT old_sec;
int old_subsec;
fixups for word relocations in writable segments, so we can adjust
them at runtime. */
static void
-ppc_elf_validate_fix (fixp, seg)
- fixS *fixp;
- segT seg;
+ppc_elf_validate_fix (fixS *fixp, segT seg)
{
if (fixp->fx_done || fixp->fx_pcrel)
return;
function descriptor sym if the corresponding code sym is used. */
void
-ppc_frob_file_before_adjust ()
+ppc_frob_file_before_adjust (void)
{
symbolS *symp;
asection *toc;
};
static int
-parse_toc_entry (toc_kind)
- enum toc_size_qualifier *toc_kind;
+parse_toc_entry (enum toc_size_qualifier *toc_kind)
{
char *start;
char *toc_spec;
#ifdef OBJ_ELF
#define APUID(a,v) ((((a) & 0xffff) << 16) | ((v) & 0xffff))
static void
-ppc_apuinfo_section_add (apu, version)
- unsigned int apu, version;
+ppc_apuinfo_section_add (unsigned int apu, unsigned int version)
{
unsigned int i;
/* This routine is called for each instruction to be assembled. */
void
-md_assemble (str)
- char *str;
+md_assemble (char *str)
{
char *s;
const struct powerpc_opcode *opcode;
{
unsigned int opcount;
unsigned int num_operands_expected;
- unsigned int i;
/* There is an optional operand. Count the number of
commas in the input line. */
{
insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg);
if (errmsg != (const char *) NULL)
- as_bad (errmsg);
+ as_bad ("%s", errmsg);
continue;
}
{
insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg);
if (errmsg != (const char *) NULL)
- as_bad (errmsg);
+ as_bad ("%s", errmsg);
}
if ((operand->flags & PPC_OPERAND_NEXT) != 0)
next_opindex = *opindex_ptr + 1;
explain. */
if (ex.X_op == O_symbol)
{
- assert (ex.X_add_symbol != NULL);
+ gas_assert (ex.X_add_symbol != NULL);
if (symbol_get_bfdsym (ex.X_add_symbol)->section
!= tocdata_section)
{
else
#endif /* TE_PE */
{
- if (! register_name (&ex))
+ if ((reg_names_p && (operand->flags & PPC_OPERAND_CR) != 0)
+ || !register_name (&ex))
{
+ char save_lex = lex_type['%'];
+
if ((operand->flags & PPC_OPERAND_CR) != 0)
- cr_operand = TRUE;
+ {
+ cr_operand = TRUE;
+ lex_type['%'] |= LEX_BEGIN_NAME;
+ }
expression (&ex);
cr_operand = FALSE;
+ lex_type['%'] = save_lex;
}
}
else if (ex.X_op == O_register)
{
insn = ppc_insert_operand (insn, operand, ex.X_add_number,
- (char *) NULL, 0);
+ ppc_cpu, (char *) NULL, 0);
}
else if (ex.X_op == O_constant)
{
}
#endif /* OBJ_ELF */
insn = ppc_insert_operand (insn, operand, ex.X_add_number,
- (char *) NULL, 0);
+ ppc_cpu, (char *) NULL, 0);
}
#ifdef OBJ_ELF
- else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
+ else
{
- /* Some TLS tweaks. */
- switch (reloc)
+ if (ex.X_op == O_symbol && str[0] == '(')
{
- default:
- break;
- case BFD_RELOC_PPC_TLS:
- insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2,
- (char *) NULL, 0);
- break;
- /* We'll only use the 32 (or 64) bit form of these relocations
- in constants. Instructions get the 16 bit form. */
- case BFD_RELOC_PPC_DTPREL:
- reloc = BFD_RELOC_PPC_DTPREL16;
- break;
- case BFD_RELOC_PPC_TPREL:
- reloc = BFD_RELOC_PPC_TPREL16;
- break;
- }
+ const char *sym_name = S_GET_NAME (ex.X_add_symbol);
+ if (sym_name[0] == '.')
+ ++sym_name;
- /* For the absolute forms of branches, convert the PC
- relative form back into the absolute. */
- if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
- {
- switch (reloc)
+ if (strcasecmp (sym_name, "__tls_get_addr") == 0)
{
- case BFD_RELOC_PPC_B26:
- reloc = BFD_RELOC_PPC_BA26;
- break;
- case BFD_RELOC_PPC_B16:
- reloc = BFD_RELOC_PPC_BA16;
- break;
- case BFD_RELOC_PPC_B16_BRTAKEN:
- reloc = BFD_RELOC_PPC_BA16_BRTAKEN;
- break;
- case BFD_RELOC_PPC_B16_BRNTAKEN:
- reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;
- break;
- default:
- break;
+ expressionS tls_exp;
+
+ hold = input_line_pointer;
+ input_line_pointer = str + 1;
+ expression (&tls_exp);
+ if (tls_exp.X_op == O_symbol)
+ {
+ reloc = BFD_RELOC_UNUSED;
+ if (strncasecmp (input_line_pointer, "@tlsgd)", 7) == 0)
+ {
+ reloc = BFD_RELOC_PPC_TLSGD;
+ input_line_pointer += 7;
+ }
+ else if (strncasecmp (input_line_pointer, "@tlsld)", 7) == 0)
+ {
+ reloc = BFD_RELOC_PPC_TLSLD;
+ input_line_pointer += 7;
+ }
+ if (reloc != BFD_RELOC_UNUSED)
+ {
+ SKIP_WHITESPACE ();
+ str = input_line_pointer;
+
+ if (fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+ fixups[fc].exp = tls_exp;
+ fixups[fc].opindex = *opindex_ptr;
+ fixups[fc].reloc = reloc;
+ ++fc;
+ }
+ }
+ input_line_pointer = hold;
}
}
- if (ppc_obj64
- && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
+ if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
{
+ /* Some TLS tweaks. */
switch (reloc)
{
- case BFD_RELOC_16:
- reloc = BFD_RELOC_PPC64_ADDR16_DS;
- break;
- case BFD_RELOC_LO16:
- reloc = BFD_RELOC_PPC64_ADDR16_LO_DS;
- break;
- case BFD_RELOC_16_GOTOFF:
- reloc = BFD_RELOC_PPC64_GOT16_DS;
- break;
- case BFD_RELOC_LO16_GOTOFF:
- reloc = BFD_RELOC_PPC64_GOT16_LO_DS;
- break;
- case BFD_RELOC_LO16_PLTOFF:
- reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
- break;
- case BFD_RELOC_16_BASEREL:
- reloc = BFD_RELOC_PPC64_SECTOFF_DS;
- break;
- case BFD_RELOC_LO16_BASEREL:
- reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS;
- break;
- case BFD_RELOC_PPC_TOC16:
- reloc = BFD_RELOC_PPC64_TOC16_DS;
- break;
- case BFD_RELOC_PPC64_TOC16_LO:
- reloc = BFD_RELOC_PPC64_TOC16_LO_DS;
- break;
- case BFD_RELOC_PPC64_PLTGOT16:
- reloc = BFD_RELOC_PPC64_PLTGOT16_DS;
- break;
- case BFD_RELOC_PPC64_PLTGOT16_LO:
- reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS;
- break;
- case BFD_RELOC_PPC_DTPREL16:
- reloc = BFD_RELOC_PPC64_DTPREL16_DS;
- break;
- case BFD_RELOC_PPC_DTPREL16_LO:
- reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS;
- break;
- case BFD_RELOC_PPC_TPREL16:
- reloc = BFD_RELOC_PPC64_TPREL16_DS;
+ default:
break;
- case BFD_RELOC_PPC_TPREL16_LO:
- reloc = BFD_RELOC_PPC64_TPREL16_LO_DS;
+
+ case BFD_RELOC_PPC_TLS:
+ if (!_bfd_elf_ppc_at_tls_transform (opcode->opcode, 0))
+ as_bad (_("@tls may not be used with \"%s\" operands"),
+ opcode->name);
+ else if (operand->shift != 11)
+ as_bad (_("@tls may only be used in last operand"));
+ else
+ insn = ppc_insert_operand (insn, operand,
+ ppc_obj64 ? 13 : 2,
+ ppc_cpu, (char *) NULL, 0);
break;
- case BFD_RELOC_PPC_GOT_DTPREL16:
- case BFD_RELOC_PPC_GOT_DTPREL16_LO:
- case BFD_RELOC_PPC_GOT_TPREL16:
- case BFD_RELOC_PPC_GOT_TPREL16_LO:
+
+ /* We'll only use the 32 (or 64) bit form of these relocations
+ in constants. Instructions get the 16 bit form. */
+ case BFD_RELOC_PPC_DTPREL:
+ reloc = BFD_RELOC_PPC_DTPREL16;
break;
- default:
- as_bad (_("unsupported relocation for DS offset field"));
+ case BFD_RELOC_PPC_TPREL:
+ reloc = BFD_RELOC_PPC_TPREL16;
break;
}
+
+ /* For the absolute forms of branches, convert the PC
+ relative form back into the absolute. */
+ if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
+ {
+ switch (reloc)
+ {
+ case BFD_RELOC_PPC_B26:
+ reloc = BFD_RELOC_PPC_BA26;
+ break;
+ case BFD_RELOC_PPC_B16:
+ reloc = BFD_RELOC_PPC_BA16;
+ break;
+ case BFD_RELOC_PPC_B16_BRTAKEN:
+ reloc = BFD_RELOC_PPC_BA16_BRTAKEN;
+ break;
+ case BFD_RELOC_PPC_B16_BRNTAKEN:
+ reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (ppc_obj64
+ && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
+ {
+ switch (reloc)
+ {
+ case BFD_RELOC_16:
+ reloc = BFD_RELOC_PPC64_ADDR16_DS;
+ break;
+ case BFD_RELOC_LO16:
+ reloc = BFD_RELOC_PPC64_ADDR16_LO_DS;
+ break;
+ case BFD_RELOC_16_GOTOFF:
+ reloc = BFD_RELOC_PPC64_GOT16_DS;
+ break;
+ case BFD_RELOC_LO16_GOTOFF:
+ reloc = BFD_RELOC_PPC64_GOT16_LO_DS;
+ break;
+ case BFD_RELOC_LO16_PLTOFF:
+ reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
+ break;
+ case BFD_RELOC_16_BASEREL:
+ reloc = BFD_RELOC_PPC64_SECTOFF_DS;
+ break;
+ case BFD_RELOC_LO16_BASEREL:
+ reloc = BFD_RELOC_PPC64_SECTOFF_LO_DS;
+ break;
+ case BFD_RELOC_PPC_TOC16:
+ reloc = BFD_RELOC_PPC64_TOC16_DS;
+ break;
+ case BFD_RELOC_PPC64_TOC16_LO:
+ reloc = BFD_RELOC_PPC64_TOC16_LO_DS;
+ break;
+ case BFD_RELOC_PPC64_PLTGOT16:
+ reloc = BFD_RELOC_PPC64_PLTGOT16_DS;
+ break;
+ case BFD_RELOC_PPC64_PLTGOT16_LO:
+ reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS;
+ break;
+ case BFD_RELOC_PPC_DTPREL16:
+ reloc = BFD_RELOC_PPC64_DTPREL16_DS;
+ break;
+ case BFD_RELOC_PPC_DTPREL16_LO:
+ reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS;
+ break;
+ case BFD_RELOC_PPC_TPREL16:
+ reloc = BFD_RELOC_PPC64_TPREL16_DS;
+ break;
+ case BFD_RELOC_PPC_TPREL16_LO:
+ reloc = BFD_RELOC_PPC64_TPREL16_LO_DS;
+ break;
+ case BFD_RELOC_PPC_GOT_DTPREL16:
+ case BFD_RELOC_PPC_GOT_DTPREL16_LO:
+ case BFD_RELOC_PPC_GOT_TPREL16:
+ case BFD_RELOC_PPC_GOT_TPREL16_LO:
+ break;
+ default:
+ as_bad (_("unsupported relocation for DS offset field"));
+ break;
+ }
+ }
}
/* We need to generate a fixup for this expression. */
if (fc >= MAX_INSN_FIXUPS)
as_fatal (_("too many fixups"));
fixups[fc].exp = ex;
- fixups[fc].opindex = 0;
+ fixups[fc].opindex = *opindex_ptr;
fixups[fc].reloc = reloc;
++fc;
}
-#endif /* OBJ_ELF */
-
+#else /* OBJ_ELF */
else
{
/* We need to generate a fixup for this expression. */
fixups[fc].reloc = BFD_RELOC_UNUSED;
++fc;
}
+#endif /* OBJ_ELF */
if (need_paren)
{
endc = ')';
need_paren = 0;
+ /* If expecting more operands, then we want to see "),". */
+ if (*str == endc && opindex_ptr[1] != 0)
+ {
+ do
+ ++str;
+ while (ISSPACE (*str));
+ endc = ',';
+ }
}
else if ((operand->flags & PPC_OPERAND_PARENS) != 0)
{
#ifdef OBJ_ELF
/* Do we need/want a APUinfo section? */
- if (ppc_cpu & (PPC_OPCODE_SPE
- | PPC_OPCODE_ISEL | PPC_OPCODE_EFS
- | PPC_OPCODE_BRLOCK | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
- | PPC_OPCODE_RFMCI))
+ if ((ppc_cpu & PPC_OPCODE_E500MC) != 0)
{
/* These are all version "1". */
if (opcode->flags & PPC_OPCODE_SPE)
md_apply_fix. */
for (i = 0; i < fc; i++)
{
- const struct powerpc_operand *operand;
-
- operand = &powerpc_operands[fixups[i].opindex];
if (fixups[i].reloc != BFD_RELOC_UNUSED)
{
reloc_howto_type *reloc_howto;
}
}
else
- fix_new_exp (frag_now,
- f - frag_now->fr_literal,
- 4,
- &fixups[i].exp,
- (operand->flags & PPC_OPERAND_RELATIVE) != 0,
- ((bfd_reloc_code_real_type)
- (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
+ {
+ const struct powerpc_operand *operand;
+
+ operand = &powerpc_operands[fixups[i].opindex];
+ fix_new_exp (frag_now,
+ f - frag_now->fr_literal,
+ 4,
+ &fixups[i].exp,
+ (operand->flags & PPC_OPERAND_RELATIVE) != 0,
+ ((bfd_reloc_code_real_type)
+ (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
+ }
}
}
around operands here. */
static void
-ppc_macro (str, macro)
- char *str;
- const struct powerpc_macro *macro;
+ppc_macro (char *str, const struct powerpc_macro *macro)
{
char *operands[10];
unsigned int count;
#ifdef OBJ_ELF
/* For ELF, add support for SHF_EXCLUDE and SHT_ORDERED. */
-int
-ppc_section_letter (letter, ptr_msg)
- int letter;
- char **ptr_msg;
+bfd_vma
+ppc_section_letter (int letter, char **ptr_msg)
{
if (letter == 'e')
return SHF_EXCLUDE;
return -1;
}
-int
-ppc_section_word (str, len)
- char *str;
- size_t len;
+bfd_vma
+ppc_section_word (char *str, size_t len)
{
if (len == 7 && strncmp (str, "exclude", 7) == 0)
return SHF_EXCLUDE;
}
int
-ppc_section_type (str, len)
- char *str;
- size_t len;
+ppc_section_type (char *str, size_t len)
{
if (len == 7 && strncmp (str, "ordered", 7) == 0)
return SHT_ORDERED;
}
int
-ppc_section_flags (flags, attr, type)
- int flags;
- int attr;
- int type;
+ppc_section_flags (flagword flags, bfd_vma attr, int type)
{
if (type == SHT_ORDERED)
flags |= SEC_ALLOC | SEC_LOAD | SEC_SORT_ENTRIES;
pseudo-op, but it can also take a single ASCII string. */
static void
-ppc_byte (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_byte (int ignore ATTRIBUTE_UNUSED)
{
if (*input_line_pointer != '\"')
{
aligns .comm and .lcomm to 4 bytes. */
static void
-ppc_comm (lcomm)
- int lcomm;
+ppc_comm (int lcomm)
{
asection *current_seg = now_seg;
subsegT current_subseg = now_subseg;
optional second argument is the alignment (the default is 2). */
static void
-ppc_csect (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_csect (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char endc;
if (S_GET_NAME (sym)[0] == '\0')
{
/* An unnamed csect is assumed to be [PR]. */
- symbol_get_tc (sym)->class = XMC_PR;
+ symbol_get_tc (sym)->symbol_class = XMC_PR;
}
align = 2;
/* Change to a different csect. */
static void
-ppc_change_csect (sym, align)
- symbolS *sym;
- offsetT align;
+ppc_change_csect (symbolS *sym, offsetT align)
{
if (S_IS_DEFINED (sym))
subseg_set (S_GET_SEGMENT (sym), symbol_get_tc (sym)->subseg);
data section. */
after_toc = 0;
is_code = 0;
- switch (symbol_get_tc (sym)->class)
+ switch (symbol_get_tc (sym)->symbol_class)
{
case XMC_PR:
case XMC_RO:
convenience of people who aren't used to XCOFF. */
static void
-ppc_section (type)
- int type;
+ppc_section (int type)
{
const char *name;
symbolS *sym;
we do permit the user to name the text or data section. */
static void
-ppc_named_section (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_named_section (int ignore ATTRIBUTE_UNUSED)
{
char *user_name;
const char *real_name;
/* The .extern pseudo-op. We create an undefined symbol. */
static void
-ppc_extern (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_extern (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char endc;
/* The .lglobl pseudo-op. Keep the symbol in the symbol table. */
static void
-ppc_lglobl (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_lglobl (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char endc;
although I don't know why it bothers. */
static void
-ppc_rename (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_rename (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char endc;
always zero, and I am assuming it is the type. */
static void
-ppc_stabx (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_stabx (int ignore ATTRIBUTE_UNUSED)
{
char *name;
int len;
gets an aux entry like that used for a csect. */
static void
-ppc_function (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_function (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char endc;
symbol_set_value_expression (ext_sym, &exp);
}
- if (symbol_get_tc (ext_sym)->class == -1)
- symbol_get_tc (ext_sym)->class = XMC_PR;
+ if (symbol_get_tc (ext_sym)->symbol_class == -1)
+ symbol_get_tc (ext_sym)->symbol_class = XMC_PR;
symbol_get_tc (ext_sym)->output = 1;
if (*input_line_pointer == ',')
{
- expressionS ignore;
+ expressionS exp;
/* Ignore the third argument. */
++input_line_pointer;
- expression (&ignore);
+ expression (& exp);
if (*input_line_pointer == ',')
{
/* Ignore the fourth argument. */
++input_line_pointer;
- expression (&ignore);
+ expression (& exp);
if (*input_line_pointer == ',')
{
/* The fifth argument is the function size. */
static symbolS *saved_bi_sym = 0;
static void
-ppc_bf (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_bf (int ignore ATTRIBUTE_UNUSED)
{
symbolS *sym;
most recent ".bf" symbol. */
static void
-ppc_ef (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_ef (int ignore ATTRIBUTE_UNUSED)
{
symbolS *sym;
is encountered. */
static void
-ppc_biei (ei)
- int ei;
+ppc_biei (int ei)
{
static symbolS *last_biei;
.bs symbol is the index of this csect symbol. */
static void
-ppc_bs (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_bs (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char endc;
/* The .es pseudo-op. Generate a C_ESTART symbol named .es. */
static void
-ppc_es (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_es (int ignore ATTRIBUTE_UNUSED)
{
symbolS *sym;
line number. */
static void
-ppc_bb (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_bb (int ignore ATTRIBUTE_UNUSED)
{
symbolS *sym;
line number. */
static void
-ppc_eb (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_eb (int ignore ATTRIBUTE_UNUSED)
{
symbolS *sym;
specified name. */
static void
-ppc_bc (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_bc (int ignore ATTRIBUTE_UNUSED)
{
char *name;
int len;
/* The .ec pseudo-op. This just creates a C_ECOMM symbol. */
static void
-ppc_ec (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_ec (int ignore ATTRIBUTE_UNUSED)
{
symbolS *sym;
/* The .toc pseudo-op. Switch to the .toc subsegment. */
static void
-ppc_toc (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_toc (int ignore ATTRIBUTE_UNUSED)
{
if (ppc_toc_csect != (symbolS *) NULL)
subseg_set (data_section, symbol_get_tc (ppc_toc_csect)->subseg);
.short pseudo-op, and we want to be compatible. */
static void
-ppc_xcoff_cons (log_size)
- int log_size;
+ppc_xcoff_cons (int log_size)
{
frag_align (log_size, 0, 0);
record_alignment (now_seg, log_size);
}
static void
-ppc_vbyte (dummy)
- int dummy ATTRIBUTE_UNUSED;
+ppc_vbyte (int dummy ATTRIBUTE_UNUSED)
{
expressionS exp;
int byte_count;
the first argument is simply ignored. */
static void
-ppc_tc (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_tc (int ignore ATTRIBUTE_UNUSED)
{
#ifdef OBJ_XCOFF
symbolS *label;
label = symbol_get_tc (ppc_current_csect)->within;
- if (symbol_get_tc (label)->class != XMC_TC0)
+ if (symbol_get_tc (label)->symbol_class != XMC_TC0)
{
as_bad (_(".tc with no label"));
ignore_rest_of_line ();
S_SET_SEGMENT (sym, now_seg);
symbol_set_frag (sym, frag_now);
S_SET_VALUE (sym, (valueT) frag_now_fix ());
- symbol_get_tc (sym)->class = XMC_TC;
+ symbol_get_tc (sym)->symbol_class = XMC_TC;
symbol_get_tc (sym)->output = 1;
ppc_frob_label (sym);
/* Skip the TOC symbol name. */
while (is_part_of_name (*input_line_pointer)
+ || *input_line_pointer == ' '
|| *input_line_pointer == '['
|| *input_line_pointer == ']'
|| *input_line_pointer == '{'
/* Pseudo-op .machine. */
static void
-ppc_machine (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_machine (int ignore ATTRIBUTE_UNUSED)
{
char *cpu_string;
#define MAX_HISTORY 100
- static unsigned long *cpu_history;
+ static ppc_cpu_t *cpu_history;
static int curr_hist;
SKIP_WHITESPACE ();
if (cpu_string != NULL)
{
- unsigned long old_cpu = ppc_cpu;
+ ppc_cpu_t old_cpu = ppc_cpu;
+ ppc_cpu_t new_cpu;
char *p;
for (p = cpu_string; *p != 0; p++)
else
ppc_cpu = cpu_history[--curr_hist];
}
- else if (parse_cpu (cpu_string))
- ;
+ else if ((new_cpu = ppc_parse_cpu (ppc_cpu, cpu_string)) != 0)
+ ppc_cpu = new_cpu;
else
as_bad (_("invalid machine `%s'"), cpu_string);
/* See whether a symbol is in the TOC section. */
static int
-ppc_is_toc_sym (sym)
- symbolS *sym;
+ppc_is_toc_sym (symbolS *sym)
{
#ifdef OBJ_XCOFF
- return symbol_get_tc (sym)->class == XMC_TC;
+ return symbol_get_tc (sym)->symbol_class == XMC_TC;
#endif
#ifdef OBJ_ELF
const char *sname = segment_name (S_GET_SEGMENT (sym));
/* Set the current section. */
static void
-ppc_set_current_section (new)
- segT new;
+ppc_set_current_section (segT new)
{
ppc_previous_section = ppc_current_section;
ppc_current_section = new;
warnings: "No previous section" */
static void
-ppc_previous (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_previous (int ignore ATTRIBUTE_UNUSED)
{
symbolS *tmp;
handling, debugging, etc. */
static void
-ppc_pdata (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_pdata (int ignore ATTRIBUTE_UNUSED)
{
if (pdata_section == 0)
{
debugging, etc. */
static void
-ppc_ydata (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_ydata (int ignore ATTRIBUTE_UNUSED)
{
if (ydata_section == 0)
{
function descriptors, etc. */
static void
-ppc_reldata (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_reldata (int ignore ATTRIBUTE_UNUSED)
{
if (reldata_section == 0)
{
3 - double word aligned (that would be 4 byte boundary) */
static void
-ppc_rdata (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_rdata (int ignore ATTRIBUTE_UNUSED)
{
if (rdata_section == 0)
{
warnings: None */
static void
-ppc_ualong (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_ualong (int ignore ATTRIBUTE_UNUSED)
{
/* Try for long. */
cons (4);
warnings: Missing symbol name */
static void
-ppc_znop (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_znop (int ignore ATTRIBUTE_UNUSED)
{
unsigned long insn;
const struct powerpc_opcode *opcode;
warnings: */
static void
-ppc_pe_comm (lcomm)
- int lcomm;
+ppc_pe_comm (int lcomm)
{
- register char *name;
- register char c;
- register char *p;
+ char *name;
+ char c;
+ char *p;
offsetT temp;
- register symbolS *symbolP;
+ symbolS *symbolP;
offsetT align;
name = input_line_pointer;
*/
void
-ppc_pe_section (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_pe_section (int ignore ATTRIBUTE_UNUSED)
{
/* Strip out the section name. */
char *section_name;
case 'R': /* Remove section at link time */
flags |= SEC_NEVER_LOAD;
break;
-
+#if IFLICT_BRAIN_DAMAGE
/* Section Protection */
case 'r': /* section is readable */
flags |= IMAGE_SCN_MEM_READ;
flags |= IMAGE_SCN_ALIGN_64BYTES;
align = 6;
break;
-
+#endif
default:
as_bad (_("unknown section attribute '%c'"),
*input_line_pointer);
}
bfd_set_section_alignment (stdoutput, sec, align);
-
}
static void
-ppc_pe_function (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_pe_function (int ignore ATTRIBUTE_UNUSED)
{
char *name;
char endc;
}
static void
-ppc_pe_tocd (ignore)
- int ignore ATTRIBUTE_UNUSED;
+ppc_pe_tocd (int ignore ATTRIBUTE_UNUSED)
{
if (tocdata_section == 0)
{
/* Don't adjust TOC relocs to use the section symbol. */
int
-ppc_pe_fix_adjustable (fix)
- fixS *fix;
+ppc_pe_fix_adjustable (fixS *fix)
{
return fix->fx_r_type != BFD_RELOC_PPC_TOC16;
}
any, to use square brackets, and to be in upper case. */
char *
-ppc_canonicalize_symbol_name (name)
- char *name;
+ppc_canonicalize_symbol_name (char *name)
{
char *s;
called whenever a new symbol is created. */
void
-ppc_symbol_new_hook (sym)
- symbolS *sym;
+ppc_symbol_new_hook (symbolS *sym)
{
struct ppc_tc_sy *tc;
const char *s;
tc = symbol_get_tc (sym);
tc->next = NULL;
tc->output = 0;
- tc->class = -1;
+ tc->symbol_class = -1;
tc->real_name = NULL;
tc->subseg = 0;
tc->align = 0;
{
case 'B':
if (strcmp (s, "BS]") == 0)
- tc->class = XMC_BS;
+ tc->symbol_class = XMC_BS;
break;
case 'D':
if (strcmp (s, "DB]") == 0)
- tc->class = XMC_DB;
+ tc->symbol_class = XMC_DB;
else if (strcmp (s, "DS]") == 0)
- tc->class = XMC_DS;
+ tc->symbol_class = XMC_DS;
break;
case 'G':
if (strcmp (s, "GL]") == 0)
- tc->class = XMC_GL;
+ tc->symbol_class = XMC_GL;
break;
case 'P':
if (strcmp (s, "PR]") == 0)
- tc->class = XMC_PR;
+ tc->symbol_class = XMC_PR;
break;
case 'R':
if (strcmp (s, "RO]") == 0)
- tc->class = XMC_RO;
+ tc->symbol_class = XMC_RO;
else if (strcmp (s, "RW]") == 0)
- tc->class = XMC_RW;
+ tc->symbol_class = XMC_RW;
break;
case 'S':
if (strcmp (s, "SV]") == 0)
- tc->class = XMC_SV;
+ tc->symbol_class = XMC_SV;
break;
case 'T':
if (strcmp (s, "TC]") == 0)
- tc->class = XMC_TC;
+ tc->symbol_class = XMC_TC;
else if (strcmp (s, "TI]") == 0)
- tc->class = XMC_TI;
+ tc->symbol_class = XMC_TI;
else if (strcmp (s, "TB]") == 0)
- tc->class = XMC_TB;
+ tc->symbol_class = XMC_TB;
else if (strcmp (s, "TC0]") == 0 || strcmp (s, "T0]") == 0)
- tc->class = XMC_TC0;
+ tc->symbol_class = XMC_TC0;
break;
case 'U':
if (strcmp (s, "UA]") == 0)
- tc->class = XMC_UA;
+ tc->symbol_class = XMC_UA;
else if (strcmp (s, "UC]") == 0)
- tc->class = XMC_UC;
+ tc->symbol_class = XMC_UC;
break;
case 'X':
if (strcmp (s, "XO]") == 0)
- tc->class = XMC_XO;
+ tc->symbol_class = XMC_XO;
break;
}
- if (tc->class == -1)
+ if (tc->symbol_class == -1)
as_bad (_("Unrecognized symbol suffix"));
}
follows the csect symbol. */
void
-ppc_frob_label (sym)
- symbolS *sym;
+ppc_frob_label (symbolS *sym)
{
if (ppc_current_csect != (symbolS *) NULL)
{
- if (symbol_get_tc (sym)->class == -1)
- symbol_get_tc (sym)->class = symbol_get_tc (ppc_current_csect)->class;
+ if (symbol_get_tc (sym)->symbol_class == -1)
+ symbol_get_tc (sym)->symbol_class = symbol_get_tc (ppc_current_csect)->symbol_class;
symbol_remove (sym, &symbol_rootP, &symbol_lastP);
symbol_append (sym, symbol_get_tc (ppc_current_csect)->within,
symbol table. */
int
-ppc_frob_symbol (sym)
- symbolS *sym;
+ppc_frob_symbol (symbolS *sym)
{
static symbolS *ppc_last_function;
static symbolS *set_end;
S_SET_STORAGE_CLASS (sym, C_HIDEXT);
if (S_GET_STORAGE_CLASS (sym) == C_EXT
+ || S_GET_STORAGE_CLASS (sym) == C_AIX_WEAKEXT
|| S_GET_STORAGE_CLASS (sym) == C_HIDEXT)
{
int i;
i = S_GET_NUMBER_AUXILIARY (sym);
S_SET_NUMBER_AUXILIARY (sym, i + 1);
a = &coffsymbol (symbol_get_bfdsym (sym))->native[i + 1].u.auxent;
- if (symbol_get_tc (sym)->class == XMC_TC0)
+ if (symbol_get_tc (sym)->symbol_class == XMC_TC0)
{
/* This is the TOC table. */
know (strcmp (S_GET_NAME (sym), "TOC") == 0);
a->x_csect.x_scnlen.l = symbol_get_frag (sym)->fr_offset;
a->x_csect.x_smtyp = (symbol_get_tc (sym)->align << 3) | XTY_CM;
if (S_IS_EXTERNAL (sym))
- symbol_get_tc (sym)->class = XMC_RW;
+ symbol_get_tc (sym)->symbol_class = XMC_RW;
else
- symbol_get_tc (sym)->class = XMC_BS;
+ symbol_get_tc (sym)->symbol_class = XMC_BS;
}
else if (S_GET_SEGMENT (sym) == absolute_section)
{
ppc_adjust_symtab. */
ppc_saw_abs = TRUE;
a->x_csect.x_smtyp = XTY_LD;
- if (symbol_get_tc (sym)->class == -1)
- symbol_get_tc (sym)->class = XMC_XO;
+ if (symbol_get_tc (sym)->symbol_class == -1)
+ symbol_get_tc (sym)->symbol_class = XMC_XO;
}
else if (! S_IS_DEFINED (sym))
{
a->x_csect.x_scnlen.l = 0;
a->x_csect.x_smtyp = XTY_ER;
}
- else if (symbol_get_tc (sym)->class == XMC_TC)
+ else if (symbol_get_tc (sym)->symbol_class == XMC_TC)
{
symbolS *next;
/* This is a TOC definition. x_scnlen is the size of the
TOC entry. */
next = symbol_next (sym);
- while (symbol_get_tc (next)->class == XMC_TC0)
+ while (symbol_get_tc (next)->symbol_class == XMC_TC0)
next = symbol_next (next);
if (next == (symbolS *) NULL
- || symbol_get_tc (next)->class != XMC_TC)
+ || symbol_get_tc (next)->symbol_class != XMC_TC)
{
if (ppc_after_toc_frag == (fragS *) NULL)
a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
a->x_csect.x_parmhash = 0;
a->x_csect.x_snhash = 0;
- if (symbol_get_tc (sym)->class == -1)
+ if (symbol_get_tc (sym)->symbol_class == -1)
a->x_csect.x_smclas = XMC_PR;
else
- a->x_csect.x_smclas = symbol_get_tc (sym)->class;
+ a->x_csect.x_smclas = symbol_get_tc (sym)->symbol_class;
a->x_csect.x_stab = 0;
a->x_csect.x_snstab = 0;
absolute symbols. */
void
-ppc_adjust_symtab ()
+ppc_adjust_symtab (void)
{
symbolS *sym;
turn. */
void
-ppc_frob_section (sec)
- asection *sec;
+ppc_frob_section (asection *sec)
{
static bfd_vma vma = 0;
#endif /* OBJ_XCOFF */
\f
-/* Turn a string in input_line_pointer into a floating point constant
- of type TYPE, and store the appropriate bytes in *LITP. The number
- of LITTLENUMS emitted is stored in *SIZEP. An error message is
- returned, or NULL on OK. */
-
char *
-md_atof (type, litp, sizep)
- int type;
- char *litp;
- int *sizep;
+md_atof (int type, char *litp, int *sizep)
{
- int prec;
- LITTLENUM_TYPE words[4];
- char *t;
- int i;
-
- switch (type)
- {
- case 'f':
- prec = 2;
- break;
-
- case 'd':
- prec = 4;
- break;
-
- default:
- *sizep = 0;
- return _("bad call to md_atof");
- }
-
- t = atof_ieee (input_line_pointer, type, words);
- if (t)
- input_line_pointer = t;
-
- *sizep = prec * 2;
-
- if (target_big_endian)
- {
- for (i = 0; i < prec; i++)
- {
- md_number_to_chars (litp, (valueT) words[i], 2);
- litp += 2;
- }
- }
- else
- {
- for (i = prec - 1; i >= 0; i--)
- {
- md_number_to_chars (litp, (valueT) words[i], 2);
- litp += 2;
- }
- }
-
- return NULL;
+ return ieee_md_atof (type, litp, sizep, target_big_endian);
}
/* Write a value out to the object file, using the appropriate
endianness. */
void
-md_number_to_chars (buf, val, n)
- char *buf;
- valueT val;
- int n;
+md_number_to_chars (char *buf, valueT val, int n)
{
if (target_big_endian)
number_to_chars_bigendian (buf, val, n);
/* We don't have any form of relaxing. */
int
-md_estimate_size_before_relax (fragp, seg)
- fragS *fragp ATTRIBUTE_UNUSED;
- asection *seg ATTRIBUTE_UNUSED;
+md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
+ asection *seg ATTRIBUTE_UNUSED)
{
abort ();
return 0;
/* Convert a machine dependent frag. We never generate these. */
void
-md_convert_frag (abfd, sec, fragp)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *sec ATTRIBUTE_UNUSED;
- fragS *fragp ATTRIBUTE_UNUSED;
+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *sec ATTRIBUTE_UNUSED,
+ fragS *fragp ATTRIBUTE_UNUSED)
{
abort ();
}
/* We have no need to default values of symbols. */
symbolS *
-md_undefined_symbol (name)
- char *name ATTRIBUTE_UNUSED;
+md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
{
return 0;
}
given a PC relative reloc. */
long
-md_pcrel_from_section (fixp, sec)
- fixS *fixp;
- segT sec ATTRIBUTE_UNUSED;
+md_pcrel_from_section (fixS *fixp, segT sec ATTRIBUTE_UNUSED)
{
return fixp->fx_frag->fr_address + fixp->fx_where;
}
corresponding .tc symbol. */
int
-ppc_fix_adjustable (fix)
- fixS *fix;
+ppc_fix_adjustable (fixS *fix)
{
valueT val = resolve_symbol_value (fix->fx_addsy);
segT symseg = S_GET_SEGMENT (fix->fx_addsy);
{
TC_SYMFIELD_TYPE *sy_tc = symbol_get_tc (sy);
- if (sy_tc->class == XMC_TC0)
+ if (sy_tc->symbol_class == XMC_TC0)
continue;
- if (sy_tc->class != XMC_TC)
+ if (sy_tc->symbol_class != XMC_TC)
break;
if (val == resolve_symbol_value (sy))
{
/* Possibly adjust the reloc to be against the csect. */
tc = symbol_get_tc (fix->fx_addsy);
if (tc->subseg == 0
- && tc->class != XMC_TC0
- && tc->class != XMC_TC
+ && tc->symbol_class != XMC_TC0
+ && tc->symbol_class != XMC_TC
&& symseg != bss_section
/* Don't adjust if this is a reloc in the toc section. */
&& (symseg != data_section
between two csects in the same section. */
int
-ppc_force_relocation (fix)
- fixS *fix;
+ppc_force_relocation (fixS *fix)
{
/* At this point fix->fx_addsy should already have been converted to
a csect symbol. If the csect does not include the fragment, then
will be emitted for a fixup. */
int
-ppc_force_relocation (fix)
- fixS *fix;
+ppc_force_relocation (fixS *fix)
{
/* Branch prediction relocations must force a relocation, as must
the vtable description relocs. */
}
int
-ppc_fix_adjustable (fix)
- fixS *fix;
+ppc_fix_adjustable (fixS *fix)
{
return (fix->fx_r_type != BFD_RELOC_16_GOTOFF
&& fix->fx_r_type != BFD_RELOC_LO16_GOTOFF
fragP->fr_var = 4;
md_number_to_chars (dest, 0x60000000, 4);
- if ((ppc_cpu & PPC_OPCODE_POWER6) != 0)
+ if ((ppc_cpu & PPC_OPCODE_POWER6) != 0
+ || (ppc_cpu & PPC_OPCODE_POWER7) != 0)
{
- /* For power6, we want the last nop to be a group terminating
- one, "ori 1,1,0". 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 and power7, 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);
dest = group_nop->fr_literal;
}
- md_number_to_chars (dest, 0x60210000, 4);
+ if ((ppc_cpu & PPC_OPCODE_POWER7) != 0)
+ /* power7 group terminating nop: "ori 2,2,0". */
+ md_number_to_chars (dest, 0x60420000, 4);
+ else
+ /* power6 group terminating nop: "ori 1,1,0". */
+ md_number_to_chars (dest, 0x60210000, 4);
}
}
}
fixup. */
void
-md_apply_fix (fixP, valP, seg)
- fixS *fixP;
- valueT * valP;
- segT seg ATTRIBUTE_UNUSED;
+md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
valueT value = * valP;
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
- result of md_pcrel_from. This is confusing. */
+ However, if the reloc is not fully resolved we do not want to
+ use *valP, and must use fx_offset instead. If the relocation
+ is PC-relative, we then need to re-apply md_pcrel_from_section
+ to this new relocation value. */
if (fixP->fx_addsy == (symbolS *) NULL)
fixP->fx_done = 1;
- else if (fixP->fx_pcrel)
- ;
-
else
- value = fixP->fx_offset;
+ {
+ value = fixP->fx_offset;
+ if (fixP->fx_pcrel)
+ value -= md_pcrel_from_section (fixP, seg);
+ }
#endif
if (fixP->fx_subsy != (symbolS *) NULL)
&& (operand->insert == NULL || ppc_obj64)
&& fixP->fx_addsy != NULL
&& symbol_get_tc (fixP->fx_addsy)->subseg != 0
- && symbol_get_tc (fixP->fx_addsy)->class != XMC_TC
- && symbol_get_tc (fixP->fx_addsy)->class != XMC_TC0
+ && symbol_get_tc (fixP->fx_addsy)->symbol_class != XMC_TC
+ && symbol_get_tc (fixP->fx_addsy)->symbol_class != XMC_TC0
&& S_GET_SEGMENT (fixP->fx_addsy) != bss_section)
{
value = fixP->fx_offset;
else
insn = bfd_getl32 ((unsigned char *) where);
insn = ppc_insert_operand (insn, operand, (offsetT) value,
+ fixP->tc_fix_data.ppc_cpu,
fixP->fx_file, fixP->fx_line);
if (target_big_endian)
bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
/* Nothing else to do here. */
return;
- assert (fixP->fx_addsy != NULL);
+ gas_assert (fixP->fx_addsy != NULL);
/* Determine a BFD reloc value based on the operand information.
We are only prepared to turn a few of the operands into
break;
case BFD_RELOC_PPC_TLS:
+ case BFD_RELOC_PPC_TLSGD:
+ case BFD_RELOC_PPC_TLSLD:
break;
case BFD_RELOC_PPC_DTPMOD:
#ifdef TE_PE
fixP->fx_addnumber = 0;
#else
- /* We want to use the offset within the data segment of the
- symbol, not the actual VMA of the symbol. */
+ /* We want to use the offset within the toc, not the actual VMA
+ of the symbol. */
fixP->fx_addnumber =
- - bfd_get_section_vma (stdoutput, S_GET_SEGMENT (fixP->fx_addsy));
+ - bfd_get_section_vma (stdoutput, S_GET_SEGMENT (fixP->fx_addsy))
+ - S_GET_VALUE (ppc_toc_csect);
#endif
}
#endif
/* Generate a reloc for a fixup. */
arelent *
-tc_gen_reloc (seg, fixp)
- asection *seg ATTRIBUTE_UNUSED;
- fixS *fixp;
+tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
{
arelent *reloc;
}
void
-ppc_cfi_frame_initial_instructions ()
+ppc_cfi_frame_initial_instructions (void)
{
cfi_add_CFA_def_cfa (1, 0);
}