/* 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, 2008 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.
/* The type of processor we are assembling for. This is one or more
of the PPC_OPCODE flags defined in opcode/ppc.h. */
-unsigned long ppc_cpu = 0;
+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 },
{ "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 },
};
static int
parse_cpu (const char *arg)
{
- unsigned long altivec_or_spe = ppc_cpu & (PPC_OPCODE_ALTIVEC | PPC_OPCODE_SPE);
+ ppc_cpu_t retain_flags =
+ ppc_cpu & (PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX | PPC_OPCODE_SPE);
/* -mpwrx and -mpwr2 mean to assemble for the IBM POWER/2
(RIOS2). */
/* Do all PPC750s have paired single ops? */
else if (strcmp (arg, "750cl") == 0)
ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_PPCPS;
- /* -m403 and -m405 mean to assemble for the PowerPC 403/405. */
- else if (strcmp (arg, "403") == 0
- || strcmp (arg, "405") == 0)
+ else if (strcmp (arg, "403") == 0)
ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
| PPC_OPCODE_403 | PPC_OPCODE_32);
- else if (strcmp (arg, "440") == 0)
+ else if (strcmp (arg, "405") == 0)
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+ | PPC_OPCODE_403 | PPC_OPCODE_405 | PPC_OPCODE_32);
+ else if (strcmp (arg, "440") == 0
+ || strcmp (arg, "464") == 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
if (ppc_cpu == 0)
ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC;
- altivec_or_spe |= PPC_OPCODE_ALTIVEC;
+ retain_flags |= PPC_OPCODE_ALTIVEC;
+ }
+ else if (strcmp (arg, "vsx") == 0)
+ {
+ if (ppc_cpu == 0)
+ ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC;
+
+ retain_flags |= PPC_OPCODE_VSX;
}
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);
+ | PPC_OPCODE_RFMCI | PPC_OPCODE_E500MC);
+ }
+ else if (strcmp (arg, "e500mc") == 0)
+ {
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
+ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
+ | PPC_OPCODE_RFMCI | PPC_OPCODE_E500MC);
}
else if (strcmp (arg, "spe") == 0)
{
if (ppc_cpu == 0)
ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_EFS;
- altivec_or_spe |= PPC_OPCODE_SPE;
+ retain_flags |= PPC_OPCODE_SPE;
}
/* -mppc64 and -m620 mean to assemble for the 64-bit PowerPC
620. */
{
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_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
| PPC_OPCODE_64 | PPC_OPCODE_POWER4
- | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6);
+ | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
+ | PPC_OPCODE_ALTIVEC);
+ }
+ else if (strcmp (arg, "power7") == 0)
+ {
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+ | PPC_OPCODE_ISEL | PPC_OPCODE_64
+ | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5
+ | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
+ | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX);
}
else if (strcmp (arg, "cell") == 0)
{
ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
| PPC_OPCODE_64 | PPC_OPCODE_POWER4
- | PPC_OPCODE_CELL);
+ | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC);
}
/* -mcom means assemble for the common intersection between Power
and PowerPC. At present, we just allow the union, rather
else
return 0;
- /* Make sure the the Altivec and SPE bits are not lost. */
- ppc_cpu |= altivec_or_spe;
+ /* Make sure the the Altivec, VSX and SPE bits are not lost. */
+ ppc_cpu |= retain_flags;
return 1;
}
-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\
-m7400, -m7410, -m7450, -m7455\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\
-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"));
const struct powerpc_macro *macro;
const struct powerpc_macro *macro_end;
bfd_boolean bad_insn = FALSE;
- unsigned long prev_opcode = 0;
if (ppc_hash != NULL)
hash_die (ppc_hash);
{
const unsigned char *o;
unsigned long omask = op->mask;
- unsigned long major_opcode = PPC_OP (op->opcode);
- /* The major opcodes had better be sorted. Code in the disassembler
- assumes the insns are sorted according to major opcode. */
- if (major_opcode < prev_opcode)
+ if (op != powerpc_opcodes)
{
- as_bad (_("major opcode is not sorted for %s"),
- op->name);
- bad_insn = TRUE;
+ /* 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);
+ }
}
- prev_opcode = major_opcode;
/* 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;
ppc_insert_operand (unsigned long insn,
const struct powerpc_operand *operand,
offsetT val,
- unsigned long ppc_cpu,
+ ppc_cpu_t ppc_cpu,
char *file,
unsigned int line)
{
errmsg = NULL;
insn = (*operand->insert) (insn, (long) val, ppc_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;
{
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 == '+')
{
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;
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,
- ppc_cpu, (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:
+ 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)
{
#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)));
+ }
}
}
#ifdef OBJ_ELF
/* For ELF, add support for SHF_EXCLUDE and SHT_ORDERED. */
-int
+bfd_vma
ppc_section_letter (int letter, char **ptr_msg)
{
if (letter == 'e')
return -1;
}
-int
+bfd_vma
ppc_section_word (char *str, size_t len)
{
if (len == 7 && strncmp (str, "exclude", 7) == 0)
}
int
-ppc_section_flags (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;
{
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;
char *p;
for (p = cpu_string; *p != 0; p++)
break;
case BFD_RELOC_PPC_TLS:
+ case BFD_RELOC_PPC_TLSGD:
+ case BFD_RELOC_PPC_TLSLD:
break;
case BFD_RELOC_PPC_DTPMOD: