/* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
- Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
/* #ha(value) denotes the high adjusted value: bits 16 through 31 of
the indicated value, compensating for #lo() being treated as a
signed number. */
-#define PPC_HA(v) ((((v) >> 16) + (((v) >> 15) & 1)) & 0xffff)
+#define PPC_HA(v) PPC_HI ((v) + 0x8000)
/* #higher(value) denotes bits 32 through 47 of the indicated value. */
#define PPC_HIGHER(v) (((v) >> 32) & 0xffff)
/* #highera(value) denotes bits 32 through 47 of the indicated value,
compensating for #lo() being treated as a signed number. */
-#define PPC_HIGHERA(v) \
- ((((v) >> 32) + (((v) & 0xffff8000) == 0xffff8000)) & 0xffff)
+#define PPC_HIGHERA(v) PPC_HIGHER ((v) + 0x8000)
/* #highest(value) denotes bits 48 through 63 of the indicated value. */
#define PPC_HIGHEST(v) (((v) >> 48) & 0xffff)
/* #highesta(value) denotes bits 48 through 63 of the indicated value,
- compensating for #lo being treated as a signed number.
- Generate 0xffffffff8000 with arithmetic here, for portability. */
-#define PPC_HIGHESTA(v) \
- ((((v) >> 48) \
- + (((v) & (((valueT) 1 << 48) - 0x8000)) == ((valueT) 1 << 48) - 0x8000)) \
- & 0xffff)
+ compensating for #lo being treated as a signed number. */
+#define PPC_HIGHESTA(v) PPC_HIGHEST ((v) + 0x8000)
#define SEX16(val) ((((val) & 0xffff) ^ 0x8000) - 0x8000)
/* The size of the processor we are assembling for. This is either
PPC_OPCODE_32 or PPC_OPCODE_64. */
-static unsigned long ppc_size = PPC_OPCODE_32;
+static unsigned long ppc_size = (BFD_DEFAULT_TARGET_SIZE == 64
+ ? PPC_OPCODE_64
+ : PPC_OPCODE_32);
/* Whether to target xcoff64. */
static int ppc_xcoff64 = 0;
#endif /* OBJ_ELF */
\f
#ifdef OBJ_ELF
-CONST char *md_shortopts = "b:l:usm:K:VQ:";
+const char *const md_shortopts = "b:l:usm:K:VQ:";
#else
-CONST char *md_shortopts = "um:";
+const char *const md_shortopts = "um:";
#endif
-struct option md_longopts[] = {
+const struct option md_longopts[] = {
{NULL, no_argument, NULL, 0}
};
-size_t md_longopts_size = sizeof (md_longopts);
+const size_t md_longopts_size = sizeof (md_longopts);
int
md_parse_option (c, arg)
/* -mpwr means to assemble for the IBM POWER (RIOS1). */
else if (strcmp (arg, "pwr") == 0)
ppc_cpu = PPC_OPCODE_POWER;
- /* -m601 means to assemble for the Motorola PowerPC 601, which includes
+ /* -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_601;
/* -mppc, -mppc32, -m603, and -m604 mean to assemble for the
- Motorola PowerPC 603/604. */
+ PowerPC 603/604. */
else if (strcmp (arg, "ppc") == 0
|| strcmp (arg, "ppc32") == 0
- || strcmp (arg, "403") == 0
- || strcmp (arg, "405") == 0
|| strcmp (arg, "603") == 0
|| strcmp (arg, "604") == 0)
ppc_cpu = PPC_OPCODE_PPC;
- else if (strcmp (arg, "7400") == 0)
+ /* -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_403;
+ 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_ALTIVEC;
+ else if (strcmp (arg, "altivec") == 0)
+ {
+ if (ppc_cpu == 0)
+ ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC;
+ else
+ ppc_cpu |= PPC_OPCODE_ALTIVEC;
+ }
/* -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_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64;
ppc_size = PPC_OPCODE_64;
}
else if (strcmp (arg, "ppc64bridge") == 0)
{
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE;
+ ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE | PPC_OPCODE_64;
+ ppc_size = 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;
+ /* -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;
+ ppc_size = PPC_OPCODE_64;
+ }
+ else if (strcmp (arg, "power4") == 0)
+ {
+ ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4;
ppc_size = PPC_OPCODE_64;
}
/* -mcom means assemble for the common intersection between Power
fprintf (stream, _("\
PowerPC options:\n\
-u ignored\n\
--mpwrx, -mpwr2 generate code for IBM POWER/2 (RIOS2)\n\
--mpwr generate code for IBM POWER (RIOS1)\n\
--m601 generate code for Motorola PowerPC 601\n\
--mppc, -mppc32, -m403, -m405, -m603, -m604\n\
- generate code for Motorola PowerPC 603/604\n\
--mppc64, -m620 generate code for Motorola PowerPC 620\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\
+-m7400, -m7410, -m7450, -m7455\n\
+ generate code For PowerPC 7400/7410/7450/7455\n\
+-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\
-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\
#elif TE_POWERMAC
return "xcoff-powermac";
#else
- return ppc_xcoff64 ? "aixcoff64-rs6000" : "aixcoff-rs6000";
+# ifdef TE_AIX5
+ return (ppc_xcoff64 ? "aix5coff64-rs6000" : "aixcoff-rs6000");
+# else
+ return (ppc_xcoff64 ? "aixcoff64-rs6000" : "aixcoff-rs6000");
+# endif
#endif
#endif
#ifdef OBJ_ELF
+ boolean is64 = BFD_DEFAULT_TARGET_SIZE == 64 && ppc_size == PPC_OPCODE_64;
+
return (target_big_endian
- ? (BFD_DEFAULT_TARGET_SIZE == 64 ? "elf64-powerpc" : "elf32-powerpc")
- : (BFD_DEFAULT_TARGET_SIZE == 64 ? "elf64-powerpcle" : "elf32-powerpcle"));
+ ? (is64 ? "elf64-powerpc" : "elf32-powerpc")
+ : (is64 ? "elf64-powerpcle" : "elf32-powerpcle"));
#endif
}
ppc_set_cpu ();
#ifdef OBJ_ELF
- /* If we're going to generate a 64-bit ABI file, then we need
- the 64-bit capable instructions. */
- if (BFD_DEFAULT_TARGET_SIZE == 64)
- ppc_size = PPC_OPCODE_64;
-
/* Set the ELF flags if desired. */
if (ppc_flags && !msolaris)
bfd_set_private_flags (stdoutput, ppc_flags);
if ((op->flags & ppc_cpu) != 0
&& ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == 0
|| (op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == ppc_size
- || (ppc_cpu & PPC_OPCODE_64_BRIDGE) != 0))
+ || (ppc_cpu & PPC_OPCODE_64_BRIDGE) != 0)
+ && ((op->flags & (PPC_OPCODE_POWER4 | PPC_OPCODE_NOPOWER4)) == 0
+ || ((op->flags & PPC_OPCODE_POWER4)
+ == (ppc_cpu & PPC_OPCODE_POWER4))))
{
const char *retval;
const char *errmsg;
errmsg = NULL;
- insn = (*operand->insert) (insn, (long) val, &errmsg);
+ insn = (*operand->insert) (insn, (long) val, ppc_cpu | ppc_size, &errmsg);
if (errmsg != (const char *) NULL)
as_bad_where (file, line, errmsg);
}
struct map_bfd {
char *string;
int length;
- bfd_reloc_code_real_type reloc;
+ int reloc;
};
char ident[20];
char *str2;
int ch;
int len;
- struct map_bfd *ptr;
+ const struct map_bfd *ptr;
#define MAP(str,reloc) { str, sizeof (str)-1, reloc }
- static struct map_bfd mapping[] = {
- 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 ("fixup", BFD_RELOC_CTOR), /* warnings with -mrelocatable */
- MAP ("plt", BFD_RELOC_24_PLT_PCREL),
- MAP ("pltrel24", BFD_RELOC_24_PLT_PCREL),
- MAP ("copy", BFD_RELOC_PPC_COPY),
- MAP ("globdat", BFD_RELOC_PPC_GLOB_DAT),
- MAP ("local24pc", BFD_RELOC_PPC_LOCAL24PC),
- MAP ("local", BFD_RELOC_PPC_LOCAL24PC),
- MAP ("pltrel", BFD_RELOC_32_PLT_PCREL),
- MAP ("plt@l", BFD_RELOC_LO16_PLTOFF),
- MAP ("plt@h", BFD_RELOC_HI16_PLTOFF),
- MAP ("plt@ha", BFD_RELOC_HI16_S_PLTOFF),
- MAP ("sdarel", BFD_RELOC_GPREL16),
- MAP ("sectoff", BFD_RELOC_32_BASEREL),
- MAP ("sectoff@l", BFD_RELOC_LO16_BASEREL),
- MAP ("sectoff@h", BFD_RELOC_HI16_BASEREL),
- MAP ("sectoff@ha", BFD_RELOC_HI16_S_BASEREL),
- MAP ("naddr", BFD_RELOC_PPC_EMB_NADDR32),
- MAP ("naddr16", BFD_RELOC_PPC_EMB_NADDR16),
- MAP ("naddr@l", BFD_RELOC_PPC_EMB_NADDR16_LO),
- MAP ("naddr@h", BFD_RELOC_PPC_EMB_NADDR16_HI),
- MAP ("naddr@ha", BFD_RELOC_PPC_EMB_NADDR16_HA),
- MAP ("sdai16", BFD_RELOC_PPC_EMB_SDAI16),
- MAP ("sda2rel", BFD_RELOC_PPC_EMB_SDA2REL),
- MAP ("sda2i16", BFD_RELOC_PPC_EMB_SDA2I16),
- MAP ("sda21", BFD_RELOC_PPC_EMB_SDA21),
- MAP ("mrkref", BFD_RELOC_PPC_EMB_MRKREF),
- MAP ("relsect", BFD_RELOC_PPC_EMB_RELSEC16),
- MAP ("relsect@l", BFD_RELOC_PPC_EMB_RELST_LO),
- MAP ("relsect@h", BFD_RELOC_PPC_EMB_RELST_HI),
- MAP ("relsect@ha", BFD_RELOC_PPC_EMB_RELST_HA),
- MAP ("bitfld", BFD_RELOC_PPC_EMB_BIT_FLD),
- MAP ("relsda", BFD_RELOC_PPC_EMB_RELSDA),
- MAP ("xgot", BFD_RELOC_PPC_TOC16),
+ 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), /* warning with -mrelocatable */
+ 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),
#if BFD_DEFAULT_TARGET_SIZE == 64
- MAP ("higher", BFD_RELOC_PPC64_HIGHER),
- MAP ("highera", BFD_RELOC_PPC64_HIGHER_S),
- MAP ("highest", BFD_RELOC_PPC64_HIGHEST),
- MAP ("highesta", BFD_RELOC_PPC64_HIGHEST_S),
- MAP ("tocbase", BFD_RELOC_PPC64_TOC),
- MAP ("toc", BFD_RELOC_PPC_TOC16),
- MAP ("toc@l", BFD_RELOC_PPC64_TOC16_LO),
- MAP ("toc@h", BFD_RELOC_PPC64_TOC16_HI),
- MAP ("toc@ha", BFD_RELOC_PPC64_TOC16_HA),
+ 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),
#endif
- { (char *) 0, 0, BFD_RELOC_UNUSED }
+ { (char *) 0, 0, (int) BFD_RELOC_UNUSED }
};
if (*str++ != '@')
&& len == ptr->length
&& memcmp (ident, ptr->string, ptr->length) == 0)
{
+ int reloc = ptr->reloc;
+
+ if (BFD_DEFAULT_TARGET_SIZE == 64 && reloc < 0)
+ {
+ if (ppc_size != PPC_OPCODE_64)
+ return BFD_RELOC_UNUSED;
+ reloc = -reloc;
+ }
+
if (exp_p->X_add_number != 0
- && (ptr->reloc == BFD_RELOC_16_GOTOFF
- || ptr->reloc == BFD_RELOC_LO16_GOTOFF
- || ptr->reloc == BFD_RELOC_HI16_GOTOFF
- || ptr->reloc == BFD_RELOC_HI16_S_GOTOFF))
+ && (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"));
/* Now check for identifier@suffix+constant. */
*str_p = str;
if (BFD_DEFAULT_TARGET_SIZE == 64
- && ptr->reloc == BFD_RELOC_PPC64_TOC
+ && reloc == (int) BFD_RELOC_PPC64_TOC
&& exp_p->X_op == O_symbol)
{
/* This reloc type ignores the symbol. Change the symbol
exp_p->X_add_symbol = &abs_symbol;
}
- return ptr->reloc;
+ return (bfd_reloc_code_real_type) reloc;
}
return BFD_RELOC_UNUSED;
&& fixp->fx_r_type != BFD_RELOC_HI16_GOTOFF
&& fixp->fx_r_type != BFD_RELOC_LO16_GOTOFF
&& fixp->fx_r_type != BFD_RELOC_HI16_S_GOTOFF
- && fixp->fx_r_type != BFD_RELOC_32_BASEREL
+ && fixp->fx_r_type != BFD_RELOC_16_BASEREL
&& fixp->fx_r_type != BFD_RELOC_LO16_BASEREL
&& fixp->fx_r_type != BFD_RELOC_HI16_BASEREL
&& fixp->fx_r_type != BFD_RELOC_HI16_S_BASEREL
from the input. */
if ((operand->flags & PPC_OPERAND_FAKE) != 0)
{
- insn = (*operand->insert) (insn, 0L, &errmsg);
+ insn = (*operand->insert) (insn, 0L, ppc_cpu | ppc_size, &errmsg);
if (errmsg != (const char *) NULL)
as_bad (errmsg);
continue;
{
if (operand->insert)
{
- insn = (*operand->insert) (insn, 0L, &errmsg);
+ insn = (*operand->insert) (insn, 0L, ppc_cpu | ppc_size, &errmsg);
if (errmsg != (const char *) NULL)
as_bad (errmsg);
}
}
if (BFD_DEFAULT_TARGET_SIZE == 64
+ && ppc_size == PPC_OPCODE_64
&& (operand->flags & PPC_OPERAND_DS) != 0)
{
switch (reloc)
case BFD_RELOC_LO16_PLTOFF:
reloc = BFD_RELOC_PPC64_PLT16_LO_DS;
break;
- case BFD_RELOC_32_BASEREL:
+ case BFD_RELOC_16_BASEREL:
reloc = BFD_RELOC_PPC64_SECTOFF_DS;
break;
case BFD_RELOC_LO16_BASEREL:
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_fix. */
+ md_apply_fix3. */
for (i = 0; i < fc; i++)
{
const struct powerpc_operand *operand;
}
/* The .bf pseudo-op. This is just like a COFF C_FCN symbol named
- ".bf". */
+ ".bf". If the pseudo op .bi was seen before .bf, patch the .bi sym
+ with the correct line number */
+
+static symbolS *saved_bi_sym = 0;
static void
ppc_bf (ignore)
S_SET_NUMBER_AUXILIARY (sym, 1);
SA_SET_SYM_LNNO (sym, coff_line_base);
+ /* Line number for bi. */
+ if (saved_bi_sym)
+ {
+ S_SET_VALUE (saved_bi_sym, coff_n_line_nos);
+ saved_bi_sym = 0;
+ }
+
+
symbol_get_tc (sym)->output = 1;
ppc_frob_label (sym);
/* The .bi and .ei pseudo-ops. These take a string argument and
generates a C_BINCL or C_EINCL symbol, which goes at the start of
- the symbol list. */
+ the symbol list. The value of .bi will be know when the next .bf
+ is encountered. */
static void
ppc_biei (ei)
S_SET_STORAGE_CLASS (sym, ei ? C_EINCL : C_BINCL);
symbol_get_tc (sym)->output = 1;
+ /* Save bi. */
+ if (ei)
+ saved_bi_sym = 0;
+ else
+ saved_bi_sym = sym;
+
for (look = last_biei ? last_biei : symbol_rootP;
(look != (symbolS *) NULL
&& (S_GET_STORAGE_CLASS (look) == C_FILE
#endif /* OBJ_XCOFF */
#ifdef OBJ_ELF
+ int align;
/* Skip the TOC symbol name. */
while (is_part_of_name (*input_line_pointer)
++input_line_pointer;
/* Align to a four/eight byte boundary. */
- frag_align (BFD_DEFAULT_TARGET_SIZE == 64 ? 3 : 2, 0, 0);
- record_alignment (now_seg, BFD_DEFAULT_TARGET_SIZE == 64 ? 3 : 2);
+ align = BFD_DEFAULT_TARGET_SIZE == 64 && ppc_size == PPC_OPCODE_64 ? 3 : 2;
+ frag_align (align, 0, 0);
+ record_alignment (now_seg, align);
#endif /* OBJ_ELF */
if (*input_line_pointer != ',')
}
/* Pseudo-op .machine. */
-/* FIXME: `.machine' is a nop for the moment. */
+/* 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_size
+ 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)
#endif
#ifdef OBJ_ELF
const char *sname = segment_name (S_GET_SEGMENT (sym));
- if (BFD_DEFAULT_TARGET_SIZE == 64)
+ if (BFD_DEFAULT_TARGET_SIZE == 64 && ppc_size == PPC_OPCODE_64)
return strcmp (sname, ".toc") == 0;
else
return strcmp (sname, ".got") == 0;
that, we determine the correct reloc code and put it back in the
fixup. */
-int
-md_apply_fix3 (fixp, valuep, seg)
- fixS *fixp;
- valueT *valuep;
+void
+md_apply_fix3 (fixP, valP, seg)
+ fixS *fixP;
+ valueT * valP;
segT seg ATTRIBUTE_UNUSED;
{
- valueT value;
+ valueT value = * valP;
#ifdef OBJ_ELF
- value = *valuep;
- if (fixp->fx_addsy != NULL)
+ if (fixP->fx_addsy != NULL)
{
/* `*valuep' may contain the value of the symbol on which the reloc
will be based; we have to remove it. */
- if (symbol_used_in_reloc_p (fixp->fx_addsy)
- && S_GET_SEGMENT (fixp->fx_addsy) != absolute_section
- && S_GET_SEGMENT (fixp->fx_addsy) != undefined_section
- && ! bfd_is_com_section (S_GET_SEGMENT (fixp->fx_addsy)))
- value -= S_GET_VALUE (fixp->fx_addsy);
+ if (symbol_used_in_reloc_p (fixP->fx_addsy)
+ && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section
+ && S_GET_SEGMENT (fixP->fx_addsy) != undefined_section
+ && ! bfd_is_com_section (S_GET_SEGMENT (fixP->fx_addsy)))
+ value -= S_GET_VALUE (fixP->fx_addsy);
/* FIXME: Why '+'? Better yet, what exactly is '*valuep'
supposed to be? I think this is related to various similar
FIXMEs in tc-i386.c and tc-sparc.c. */
- if (fixp->fx_pcrel)
- value += fixp->fx_frag->fr_address + fixp->fx_where;
+ if (fixP->fx_pcrel)
+ value += fixP->fx_frag->fr_address + fixP->fx_where;
}
else
- {
- fixp->fx_done = 1;
- }
+ fixP->fx_done = 1;
#else
/* FIXME FIXME FIXME: The value we are passed in *valuep includes
the symbol values. Since we are using BFD_ASSEMBLER, if we are
*valuep, and must use fx_offset instead. However, if the reloc
is PC relative, we do want to use *valuep since it includes the
result of md_pcrel_from. This is confusing. */
- if (fixp->fx_addsy == (symbolS *) NULL)
- {
- value = *valuep;
- fixp->fx_done = 1;
- }
- else if (fixp->fx_pcrel)
- value = *valuep;
+ if (fixP->fx_addsy == (symbolS *) NULL)
+ fixP->fx_done = 1;
+
+ else if (fixP->fx_pcrel)
+ ;
+
else
{
- value = fixp->fx_offset;
- if (fixp->fx_subsy != (symbolS *) NULL)
+ value = fixP->fx_offset;
+ if (fixP->fx_subsy != (symbolS *) NULL)
{
- if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
- value -= S_GET_VALUE (fixp->fx_subsy);
+ if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
+ value -= S_GET_VALUE (fixP->fx_subsy);
else
{
/* We can't actually support subtracting a symbol. */
- as_bad_where (fixp->fx_file, fixp->fx_line,
+ as_bad_where (fixP->fx_file, fixP->fx_line,
_("expression too complex"));
}
}
}
#endif
- if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
+ if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
{
int opindex;
const struct powerpc_operand *operand;
char *where;
unsigned long insn;
- opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
+ opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
operand = &powerpc_operands[opindex];
if ((operand->flags & PPC_OPERAND_PARENS) != 0
&& operand->bits == 16
&& operand->shift == 0
- && operand->insert == NULL
- && 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
- && S_GET_SEGMENT (fixp->fx_addsy) != bss_section)
+ && (operand->insert == NULL || ppc_xcoff64)
+ && 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
+ && S_GET_SEGMENT (fixP->fx_addsy) != bss_section)
{
- value = fixp->fx_offset;
- fixp->fx_done = 1;
+ value = fixP->fx_offset;
+ fixP->fx_done = 1;
}
#endif
/* Fetch the instruction, insert the fully resolved operand
value, and stuff the instruction back again. */
- where = fixp->fx_frag->fr_literal + fixp->fx_where;
+ where = fixP->fx_frag->fr_literal + fixP->fx_where;
if (target_big_endian)
insn = bfd_getb32 ((unsigned char *) where);
else
insn = bfd_getl32 ((unsigned char *) where);
insn = ppc_insert_operand (insn, operand, (offsetT) value,
- fixp->fx_file, fixp->fx_line);
+ fixP->fx_file, fixP->fx_line);
if (target_big_endian)
bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
else
bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
- if (fixp->fx_done)
- {
- /* Nothing else to do here. */
- return 1;
- }
+ if (fixP->fx_done)
+ /* Nothing else to do here. */
+ return;
- assert (fixp->fx_addsy != NULL);
+ 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
if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
&& operand->bits == 26
&& operand->shift == 0)
- fixp->fx_r_type = BFD_RELOC_PPC_B26;
+ fixP->fx_r_type = BFD_RELOC_PPC_B26;
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
&& operand->bits == 16
&& operand->shift == 0)
- fixp->fx_r_type = BFD_RELOC_PPC_B16;
+ fixP->fx_r_type = BFD_RELOC_PPC_B16;
else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
&& operand->bits == 26
&& operand->shift == 0)
- fixp->fx_r_type = BFD_RELOC_PPC_BA26;
+ fixP->fx_r_type = BFD_RELOC_PPC_BA26;
else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
&& operand->bits == 16
&& operand->shift == 0)
- fixp->fx_r_type = BFD_RELOC_PPC_BA16;
+ fixP->fx_r_type = BFD_RELOC_PPC_BA16;
#if defined (OBJ_XCOFF) || defined (OBJ_ELF)
else if ((operand->flags & PPC_OPERAND_PARENS) != 0
&& operand->bits == 16
&& operand->shift == 0
- && ppc_is_toc_sym (fixp->fx_addsy))
+ && ppc_is_toc_sym (fixP->fx_addsy))
{
- fixp->fx_r_type = BFD_RELOC_PPC_TOC16;
+ fixP->fx_r_type = BFD_RELOC_PPC_TOC16;
#ifdef OBJ_ELF
if (BFD_DEFAULT_TARGET_SIZE == 64
+ && ppc_size == PPC_OPCODE_64
&& (operand->flags & PPC_OPERAND_DS) != 0)
- fixp->fx_r_type = BFD_RELOC_PPC64_TOC16_DS;
+ fixP->fx_r_type = BFD_RELOC_PPC64_TOC16_DS;
#endif
- fixp->fx_size = 2;
+ fixP->fx_size = 2;
if (target_big_endian)
- fixp->fx_where += 2;
+ fixP->fx_where += 2;
}
#endif /* defined (OBJ_XCOFF) || defined (OBJ_ELF) */
else
/* Use expr_symbol_where to see if this is an expression
symbol. */
- if (expr_symbol_where (fixp->fx_addsy, &sfile, &sline))
- as_bad_where (fixp->fx_file, fixp->fx_line,
+ if (expr_symbol_where (fixP->fx_addsy, &sfile, &sline))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
_("unresolved expression that must be resolved"));
else
- as_bad_where (fixp->fx_file, fixp->fx_line,
+ as_bad_where (fixP->fx_file, fixP->fx_line,
_("unsupported relocation against %s"),
- S_GET_NAME (fixp->fx_addsy));
- fixp->fx_done = 1;
- return 1;
+ S_GET_NAME (fixP->fx_addsy));
+ fixP->fx_done = 1;
+ return;
}
}
else
{
#ifdef OBJ_ELF
- ppc_elf_validate_fix (fixp, seg);
+ ppc_elf_validate_fix (fixP, seg);
#endif
- switch (fixp->fx_r_type)
+ switch (fixP->fx_r_type)
{
case BFD_RELOC_CTOR:
- /* FIXME: 32 bits even for 64-bit targets? */
+ if (BFD_DEFAULT_TARGET_SIZE == 64 && ppc_size == PPC_OPCODE_64)
+ goto ctor64;
+ /* fall through */
+
case BFD_RELOC_32:
- if (fixp->fx_pcrel)
- fixp->fx_r_type = BFD_RELOC_32_PCREL;
+ if (fixP->fx_pcrel)
+ fixP->fx_r_type = BFD_RELOC_32_PCREL;
/* fall through */
case BFD_RELOC_RVA:
case BFD_RELOC_32_PCREL:
- case BFD_RELOC_32_BASEREL:
case BFD_RELOC_PPC_EMB_NADDR32:
- md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
value, 4);
break;
case BFD_RELOC_64:
- if (fixp->fx_pcrel)
- fixp->fx_r_type = BFD_RELOC_64_PCREL;
+ ctor64:
+ if (fixP->fx_pcrel)
+ fixP->fx_r_type = BFD_RELOC_64_PCREL;
/* fall through */
case BFD_RELOC_64_PCREL:
- md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
value, 8);
break;
case BFD_RELOC_LO16_GOTOFF:
case BFD_RELOC_HI16_GOTOFF:
case BFD_RELOC_HI16_S_GOTOFF:
+ case BFD_RELOC_16_BASEREL:
case BFD_RELOC_LO16_BASEREL:
case BFD_RELOC_HI16_BASEREL:
case BFD_RELOC_HI16_S_BASEREL:
case BFD_RELOC_PPC64_TOC16_HA:
#endif
#endif
- if (fixp->fx_pcrel)
+ if (fixP->fx_pcrel)
{
- if (fixp->fx_addsy != NULL)
- as_bad_where (fixp->fx_file, fixp->fx_line,
+ if (fixP->fx_addsy != NULL)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
_("cannot emit PC relative %s relocation against %s"),
- bfd_get_reloc_code_name (fixp->fx_r_type),
- S_GET_NAME (fixp->fx_addsy));
+ bfd_get_reloc_code_name (fixP->fx_r_type),
+ S_GET_NAME (fixP->fx_addsy));
else
- as_bad_where (fixp->fx_file, fixp->fx_line,
+ as_bad_where (fixP->fx_file, fixP->fx_line,
_("cannot emit PC relative %s relocation"),
- bfd_get_reloc_code_name (fixp->fx_r_type));
+ bfd_get_reloc_code_name (fixP->fx_r_type));
}
- md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
value, 2);
break;
lis %r3,(L1-L2)@ha
where L1 and L2 are defined later. */
case BFD_RELOC_HI16:
- if (fixp->fx_pcrel)
+ if (fixP->fx_pcrel)
abort ();
- md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ 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)
+ if (fixP->fx_pcrel)
abort ();
- md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
PPC_HA (value), 2);
break;
#ifdef OBJ_ELF
#if BFD_DEFAULT_TARGET_SIZE == 64
case BFD_RELOC_PPC64_HIGHER:
- if (fixp->fx_pcrel)
+ if (fixP->fx_pcrel)
abort ();
- md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
PPC_HIGHER (value), 2);
break;
case BFD_RELOC_PPC64_HIGHER_S:
- if (fixp->fx_pcrel)
+ if (fixP->fx_pcrel)
abort ();
- md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
PPC_HIGHERA (value), 2);
break;
case BFD_RELOC_PPC64_HIGHEST:
- if (fixp->fx_pcrel)
+ if (fixP->fx_pcrel)
abort ();
- md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
PPC_HIGHEST (value), 2);
break;
case BFD_RELOC_PPC64_HIGHEST_S:
- if (fixp->fx_pcrel)
+ if (fixP->fx_pcrel)
abort ();
- md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
PPC_HIGHESTA (value), 2);
break;
case BFD_RELOC_PPC64_TOC16_LO_DS:
case BFD_RELOC_PPC64_PLTGOT16_DS:
case BFD_RELOC_PPC64_PLTGOT16_LO_DS:
- if (fixp->fx_pcrel)
+ if (fixP->fx_pcrel)
abort ();
{
- unsigned char *where = fixp->fx_frag->fr_literal + fixp->fx_where;
+ unsigned char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
unsigned long val;
if (target_big_endian)
/* Because SDA21 modifies the register field, the size is set to 4
bytes, rather than 2, so offset it here appropriately. */
case BFD_RELOC_PPC_EMB_SDA21:
- if (fixp->fx_pcrel)
+ if (fixP->fx_pcrel)
abort ();
- md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where
+ ((target_big_endian) ? 2 : 0),
value, 2);
break;
case BFD_RELOC_8:
- if (fixp->fx_pcrel)
+ if (fixP->fx_pcrel)
abort ();
- md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
+ md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
value, 1);
break;
case BFD_RELOC_24_PLT_PCREL:
case BFD_RELOC_PPC_LOCAL24PC:
- if (!fixp->fx_pcrel && !fixp->fx_done)
+ if (!fixP->fx_pcrel && !fixP->fx_done)
abort ();
- if (fixp->fx_done)
+ if (fixP->fx_done)
{
char *where;
unsigned long insn;
/* Fetch the instruction, insert the fully resolved operand
value, and stuff the instruction back again. */
- where = fixp->fx_frag->fr_literal + fixp->fx_where;
+ where = fixP->fx_frag->fr_literal + fixP->fx_where;
if (target_big_endian)
insn = bfd_getb32 ((unsigned char *) where);
else
insn = bfd_getl32 ((unsigned char *) where);
if ((value & 3) != 0)
- as_bad_where (fixp->fx_file, fixp->fx_line,
+ as_bad_where (fixP->fx_file, fixP->fx_line,
_("must branch to an address a multiple of 4"));
if ((offsetT) value < -0x40000000
|| (offsetT) value >= 0x40000000)
- as_bad_where (fixp->fx_file, fixp->fx_line,
+ as_bad_where (fixP->fx_file, fixP->fx_line,
_("@local or @plt branch destination is too far away, %ld bytes"),
(long) value);
insn = insn | (value & 0x03fffffc);
break;
case BFD_RELOC_VTABLE_INHERIT:
- fixp->fx_done = 0;
- if (fixp->fx_addsy
- && !S_IS_DEFINED (fixp->fx_addsy)
- && !S_IS_WEAK (fixp->fx_addsy))
- S_SET_WEAK (fixp->fx_addsy);
+ fixP->fx_done = 0;
+ if (fixP->fx_addsy
+ && !S_IS_DEFINED (fixP->fx_addsy)
+ && !S_IS_WEAK (fixP->fx_addsy))
+ S_SET_WEAK (fixP->fx_addsy);
break;
case BFD_RELOC_VTABLE_ENTRY:
- fixp->fx_done = 0;
+ fixP->fx_done = 0;
break;
#ifdef OBJ_ELF
/* Generated by reference to `sym@tocbase'. The sym is
ignored by the linker. */
case BFD_RELOC_PPC64_TOC:
- fixp->fx_done = 0;
+ fixP->fx_done = 0;
break;
#endif
#endif
default:
fprintf (stderr,
- _("Gas failure, reloc value %d\n"), fixp->fx_r_type);
+ _("Gas failure, reloc value %d\n"), fixP->fx_r_type);
fflush (stderr);
abort ();
}
}
#ifdef OBJ_ELF
- fixp->fx_addnumber = value;
+ fixP->fx_addnumber = value;
#else
- if (fixp->fx_r_type != BFD_RELOC_PPC_TOC16)
- fixp->fx_addnumber = 0;
+ if (fixP->fx_r_type != BFD_RELOC_PPC_TOC16)
+ fixP->fx_addnumber = 0;
else
{
#ifdef TE_PE
- fixp->fx_addnumber = 0;
+ 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. */
- fixp->fx_addnumber =
- - bfd_get_section_vma (stdoutput, S_GET_SEGMENT (fixp->fx_addsy));
+ fixP->fx_addnumber =
+ - bfd_get_section_vma (stdoutput, S_GET_SEGMENT (fixP->fx_addsy));
#endif
}
#endif
-
- return 1;
}
/* Generate a reloc for a fixup. */