/* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
- Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
#include "as.h"
#include "safe-ctype.h"
#include "subsegs.h"
-
+#include "dw2gencfi.h"
#include "opcode/ppc.h"
#ifdef OBJ_ELF
/* Whether to use user friendly register names. */
#ifndef TARGET_REG_NAMES_P
#ifdef TE_PE
-#define TARGET_REG_NAMES_P true
+#define TARGET_REG_NAMES_P TRUE
#else
-#define TARGET_REG_NAMES_P false
+#define TARGET_REG_NAMES_P FALSE
#endif
#endif
#define SEX16(val) ((((val) & 0xffff) ^ 0x8000) - 0x8000)
-static boolean reg_names_p = TARGET_REG_NAMES_P;
+static bfd_boolean reg_names_p = TARGET_REG_NAMES_P;
-static boolean register_name PARAMS ((expressionS *));
+static bfd_boolean register_name PARAMS ((expressionS *));
static void ppc_set_cpu PARAMS ((void));
static unsigned long ppc_insert_operand
PARAMS ((unsigned long insn, const struct powerpc_operand *operand,
static void ppc_ef PARAMS ((int));
static void ppc_es PARAMS ((int));
static void ppc_csect PARAMS ((int));
-static void ppc_change_csect PARAMS ((symbolS *));
+static void ppc_change_csect PARAMS ((symbolS *, offsetT));
static void ppc_function PARAMS ((int));
static void ppc_extern PARAMS ((int));
static void ppc_lglobl PARAMS ((int));
/* Characters which mean that a number is a floating point constant,
as in 0d1.0. */
const char FLT_CHARS[] = "dD";
+
+/* '+' and '-' can be used as postfix predicate predictors for conditional
+ branches. So they need to be accepted as symbol characters. */
+const char ppc_symbol_chars[] = "+-";
+
+/* The dwarf2 data alignment, adjusted for 32 or 64 bit. */
+int ppc_cie_data_alignment;
\f
/* The target specific pseudo-ops which we support. */
{ "rdata", ppc_elf_rdata, 0 },
{ "rodata", ppc_elf_rdata, 0 },
{ "lcomm", ppc_elf_lcomm, 0 },
- { "file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
- { "loc", dwarf2_directive_loc, 0 },
#endif
#ifdef TE_PE
* original state.
*/
-static boolean
+static bfd_boolean
register_name (expressionP)
expressionS *expressionP;
{
name = ++input_line_pointer;
else if (!reg_names_p || !ISALPHA (name[0]))
- return false;
+ return FALSE;
c = get_symbol_end ();
reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
/* Make the rest nice. */
expressionP->X_add_symbol = NULL;
expressionP->X_op_symbol = NULL;
- return true;
+ return TRUE;
}
/* Reset the line as if we had not done anything. */
input_line_pointer = start;
- return false;
+ return FALSE;
}
\f
/* This function is called for each symbol seen in an expression. It
to use for condition codes. */
/* Whether to do the special parsing. */
-static boolean cr_operand;
+static bfd_boolean cr_operand;
/* Names to recognize in a condition code. This table is sorted. */
static const struct pd_reg cr_names[] =
/* Whether this is Solaris or not. */
#ifdef TARGET_SOLARIS_COMMENT
-#define SOLARIS_P true
+#define SOLARIS_P TRUE
#else
-#define SOLARIS_P false
+#define SOLARIS_P FALSE
#endif
-static boolean msolaris = SOLARIS_P;
+static bfd_boolean msolaris = SOLARIS_P;
#endif
#ifdef OBJ_XCOFF
#define PPC_APUINFO_EFS 0x101
#define PPC_APUINFO_BRLOCK 0x102
-/*
- * We keep a list of APUinfo
+/*
+ * We keep a list of APUinfo
*/
unsigned long *ppc_apuinfo_list;
unsigned int ppc_apuinfo_num;
/* -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;
+ 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
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;
+ || 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;
+ || strcmp (arg, "7410") == 0
+ || strcmp (arg, "7450") == 0
+ || strcmp (arg, "7455") == 0)
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+ | PPC_OPCODE_ALTIVEC | PPC_OPCODE_32);
else if (strcmp (arg, "altivec") == 0)
- {
- if (ppc_cpu == 0)
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC;
- else
- ppc_cpu |= PPC_OPCODE_ALTIVEC;
- }
+ {
+ 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;
- }
+ 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)
}
else if (strcmp (arg, "ppc64bridge") == 0)
{
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
- | PPC_OPCODE_64_BRIDGE | PPC_OPCODE_64;
+ 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)
/* -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_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;
+ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+ | PPC_OPCODE_64 | PPC_OPCODE_POWER4);
}
/* -mcom means assemble for the common intersection between Power
and PowerPC. At present, we just allow the union, rather
ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
/* -many means to assemble for any architecture (PWR/PWRX/PPC). */
else if (strcmp (arg, "any") == 0)
- ppc_cpu = PPC_OPCODE_ANY | PPC_OPCODE_32;
+ ppc_cpu |= PPC_OPCODE_ANY;
else if (strcmp (arg, "regnames") == 0)
- reg_names_p = true;
+ reg_names_p = TRUE;
else if (strcmp (arg, "no-regnames") == 0)
- reg_names_p = false;
+ reg_names_p = FALSE;
#ifdef OBJ_ELF
/* -mrelocatable/-mrelocatable-lib -- warn about initializations
else if (strcmp (arg, "solaris") == 0)
{
- msolaris = true;
+ msolaris = TRUE;
ppc_comment_chars = ppc_solaris_comment_chars;
}
else if (strcmp (arg, "no-solaris") == 0)
{
- msolaris = false;
+ msolaris = FALSE;
ppc_comment_chars = ppc_eabi_comment_chars;
}
#endif
{
fprintf (stream, _("\
PowerPC options:\n\
+-a32 generate ELF32/XCOFF32\n\
+-a64 generate ELF64/XCOFF64\n\
-u ignored\n\
-mpwrx, -mpwr2 generate code for POWER/2 (RIOS2)\n\
-mpwr generate code for POWER (RIOS1)\n\
-m601 generate code for PowerPC 601\n\
-mppc, -mppc32, -m603, -m604\n\
generate code for PowerPC 603/604\n\
--m403, -m405 generate code for PowerPC 403/405\n\
+-m403, -m405 generate code for PowerPC 403/405\n\
+-m440 generate code for PowerPC 440\n\
-m7400, -m7410, -m7450, -m7455\n\
- generate code For PowerPC 7400/7410/7450/7455\n\
+ generate code For PowerPC 7400/7410/7450/7455\n"));
+ fprintf (stream, _("\
-mppc64, -m620 generate code for PowerPC 620/625/630\n\
-mppc64bridge generate code for PowerPC 64, including bridge insns\n\
-mbooke64 generate code for 64-bit PowerPC BookE\n\
-mbooke, mbooke32 generate code for 32-bit PowerPC BookE\n\
-mpower4 generate code for Power4 architecture\n\
--maltivec generate code for AltiVec\n\
-mcom generate code Power/PowerPC common instructions\n\
--many generate code for any architecture (PWR/PWRX/PPC)\n\
--mregnames Allow symbolic names for registers\n\
--mno-regnames Do not allow symbolic names for registers\n"));
+-many generate code for any architecture (PWR/PWRX/PPC)\n"));
fprintf (stream, _("\
+-maltivec generate code for AltiVec\n\
-me500, -me500x2 generate code for Motorola e500 core complex\n\
--mspe generate code for Motorola SPE instructions\n"));
+-mspe generate code for Motorola SPE instructions\n\
+-mregnames Allow symbolic names for registers\n\
+-mno-regnames Do not allow symbolic names for registers\n"));
#ifdef OBJ_ELF
fprintf (stream, _("\
-mrelocatable support for GCC's -mrelocatble option\n\
-mrelocatable-lib support for GCC's -mrelocatble-lib option\n\
-memb set PPC_EMB bit in ELF flags\n\
--mlittle, -mlittle-endian\n\
+-mlittle, -mlittle-endian, -l, -le\n\
generate code for a little endian machine\n\
--mbig, -mbig-endian generate code for a big endian machine\n\
+-mbig, -mbig-endian, -b, -be\n\
+ generate code for a big endian machine\n\
-msolaris generate code for Solaris\n\
-mno-solaris do not generate code for Solaris\n\
-V print assembler version number\n\
const char *default_os = TARGET_OS;
const char *default_cpu = TARGET_CPU;
- if (ppc_cpu == 0)
+ if ((ppc_cpu & ~PPC_OPCODE_ANY) == 0)
{
if (ppc_obj64)
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
+ ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
else if (strncmp (default_os, "aix", 3) == 0
&& default_os[3] >= '4' && default_os[3] <= '9')
- ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32;
+ ppc_cpu |= PPC_OPCODE_COMMON | PPC_OPCODE_32;
else if (strncmp (default_os, "aix3", 4) == 0)
- ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
+ ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
else if (strcmp (default_cpu, "rs6000") == 0)
- ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32;
+ ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
else if (strncmp (default_cpu, "powerpc", 7) == 0)
- {
- if (default_cpu[7] == '6' && default_cpu[8] == '4')
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
- else
- ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
- }
+ {
+ if (default_cpu[7] == '6' && default_cpu[8] == '4')
+ ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
+ else
+ ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
+ }
else
as_fatal (_("Unknown default cpu = %s, os = %s"),
default_cpu, default_os);
const struct powerpc_opcode *op_end;
const struct powerpc_macro *macro;
const struct powerpc_macro *macro_end;
- boolean dup_insn = false;
+ bfd_boolean dup_insn = FALSE;
ppc_set_cpu ();
+ ppc_cie_data_alignment = ppc_obj64 ? -8 : -4;
+
#ifdef OBJ_ELF
/* Set the ELF flags if desired. */
if (ppc_flags && !msolaris)
as_bad (_("Internal assembler error for instruction %s"),
op->name);
- dup_insn = true;
+ dup_insn = TRUE;
}
}
}
+ if ((ppc_cpu & PPC_OPCODE_ANY) != 0)
+ for (op = powerpc_opcodes; op < op_end; op++)
+ hash_insert (ppc_hash, op->name, (PTR) op);
+
/* Insert the macros into a hash table. */
ppc_macro_hash = hash_new ();
if (retval != (const char *) NULL)
{
as_bad (_("Internal assembler error for macro %s"), macro->name);
- dup_insn = true;
+ dup_insn = TRUE;
}
}
}
asection *seg = now_seg;
subsegT subseg = now_subseg;
asection *apuinfo_secp = (asection *) NULL;
- int i;
+ unsigned int i;
/* Create the .PPC.EMB.apuinfo section. */
apuinfo_secp = subseg_new (".PPC.EMB.apuinfo", 0);
bfd_set_section_flags (stdoutput,
apuinfo_secp,
- SEC_HAS_CONTENTS | SEC_READONLY | SEC_MERGE);
+ SEC_HAS_CONTENTS | SEC_READONLY);
p = frag_more (4);
md_number_to_chars (p, (valueT) 8, 4);
p = frag_more (4);
- md_number_to_chars (p, (valueT) ppc_apuinfo_num, 4);
+ md_number_to_chars (p, (valueT) ppc_apuinfo_num * 4, 4);
p = frag_more (4);
md_number_to_chars (p, (valueT) 2, 4);
for (i = 0; i < ppc_apuinfo_num; i++)
{
- p = frag_more (4);
- md_number_to_chars (p, (valueT) ppc_apuinfo_list[i], 4);
+ p = frag_more (4);
+ md_number_to_chars (p, (valueT) ppc_apuinfo_list[i], 4);
}
frag_align (2, 0, 0);
#define MAP(str,reloc) { str, sizeof (str)-1, reloc }
static const struct map_bfd mapping[] = {
- MAP ("l", (int) BFD_RELOC_LO16),
- MAP ("h", (int) BFD_RELOC_HI16),
- MAP ("ha", (int) BFD_RELOC_HI16_S),
- MAP ("brtaken", (int) BFD_RELOC_PPC_B16_BRTAKEN),
- MAP ("brntaken", (int) BFD_RELOC_PPC_B16_BRNTAKEN),
- MAP ("got", (int) BFD_RELOC_16_GOTOFF),
- MAP ("got@l", (int) BFD_RELOC_LO16_GOTOFF),
- MAP ("got@h", (int) BFD_RELOC_HI16_GOTOFF),
- MAP ("got@ha", (int) BFD_RELOC_HI16_S_GOTOFF),
- MAP ("fixup", (int) BFD_RELOC_CTOR), /* 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),
+ MAP ("l", (int) BFD_RELOC_LO16),
+ MAP ("h", (int) BFD_RELOC_HI16),
+ MAP ("ha", (int) BFD_RELOC_HI16_S),
+ MAP ("brtaken", (int) BFD_RELOC_PPC_B16_BRTAKEN),
+ MAP ("brntaken", (int) BFD_RELOC_PPC_B16_BRNTAKEN),
+ MAP ("got", (int) BFD_RELOC_16_GOTOFF),
+ MAP ("got@l", (int) BFD_RELOC_LO16_GOTOFF),
+ MAP ("got@h", (int) BFD_RELOC_HI16_GOTOFF),
+ MAP ("got@ha", (int) BFD_RELOC_HI16_S_GOTOFF),
+ MAP ("fixup", (int) BFD_RELOC_CTOR),
+ MAP ("plt", (int) BFD_RELOC_24_PLT_PCREL),
+ MAP ("pltrel24", (int) BFD_RELOC_24_PLT_PCREL),
+ MAP ("copy", (int) BFD_RELOC_PPC_COPY),
+ MAP ("globdat", (int) BFD_RELOC_PPC_GLOB_DAT),
+ MAP ("local24pc", (int) BFD_RELOC_PPC_LOCAL24PC),
+ MAP ("local", (int) BFD_RELOC_PPC_LOCAL24PC),
+ MAP ("pltrel", (int) BFD_RELOC_32_PLT_PCREL),
+ MAP ("plt@l", (int) BFD_RELOC_LO16_PLTOFF),
+ MAP ("plt@h", (int) BFD_RELOC_HI16_PLTOFF),
+ MAP ("plt@ha", (int) BFD_RELOC_HI16_S_PLTOFF),
+ MAP ("sdarel", (int) BFD_RELOC_GPREL16),
+ MAP ("sectoff", (int) BFD_RELOC_16_BASEREL),
+ MAP ("sectoff@l", (int) BFD_RELOC_LO16_BASEREL),
+ MAP ("sectoff@h", (int) BFD_RELOC_HI16_BASEREL),
+ MAP ("sectoff@ha", (int) BFD_RELOC_HI16_S_BASEREL),
+ MAP ("naddr", (int) BFD_RELOC_PPC_EMB_NADDR32),
+ MAP ("naddr16", (int) BFD_RELOC_PPC_EMB_NADDR16),
+ MAP ("naddr@l", (int) BFD_RELOC_PPC_EMB_NADDR16_LO),
+ MAP ("naddr@h", (int) BFD_RELOC_PPC_EMB_NADDR16_HI),
+ MAP ("naddr@ha", (int) BFD_RELOC_PPC_EMB_NADDR16_HA),
+ MAP ("sdai16", (int) BFD_RELOC_PPC_EMB_SDAI16),
+ MAP ("sda2rel", (int) BFD_RELOC_PPC_EMB_SDA2REL),
+ MAP ("sda2i16", (int) BFD_RELOC_PPC_EMB_SDA2I16),
+ MAP ("sda21", (int) BFD_RELOC_PPC_EMB_SDA21),
+ MAP ("mrkref", (int) BFD_RELOC_PPC_EMB_MRKREF),
+ MAP ("relsect", (int) BFD_RELOC_PPC_EMB_RELSEC16),
+ MAP ("relsect@l", (int) BFD_RELOC_PPC_EMB_RELST_LO),
+ MAP ("relsect@h", (int) BFD_RELOC_PPC_EMB_RELST_HI),
+ MAP ("relsect@ha", (int) BFD_RELOC_PPC_EMB_RELST_HA),
+ MAP ("bitfld", (int) BFD_RELOC_PPC_EMB_BIT_FLD),
+ MAP ("relsda", (int) BFD_RELOC_PPC_EMB_RELSDA),
+ MAP ("xgot", (int) BFD_RELOC_PPC_TOC16),
+ MAP ("tls", (int) BFD_RELOC_PPC_TLS),
+ MAP ("dtpmod", (int) BFD_RELOC_PPC_DTPMOD),
+ MAP ("dtprel", (int) BFD_RELOC_PPC_DTPREL),
+ MAP ("dtprel@l", (int) BFD_RELOC_PPC_DTPREL16_LO),
+ MAP ("dtprel@h", (int) BFD_RELOC_PPC_DTPREL16_HI),
+ MAP ("dtprel@ha", (int) BFD_RELOC_PPC_DTPREL16_HA),
+ MAP ("tprel", (int) BFD_RELOC_PPC_TPREL),
+ MAP ("tprel@l", (int) BFD_RELOC_PPC_TPREL16_LO),
+ MAP ("tprel@h", (int) BFD_RELOC_PPC_TPREL16_HI),
+ MAP ("tprel@ha", (int) BFD_RELOC_PPC_TPREL16_HA),
+ MAP ("got@tlsgd", (int) BFD_RELOC_PPC_GOT_TLSGD16),
+ MAP ("got@tlsgd@l", (int) BFD_RELOC_PPC_GOT_TLSGD16_LO),
+ MAP ("got@tlsgd@h", (int) BFD_RELOC_PPC_GOT_TLSGD16_HI),
+ MAP ("got@tlsgd@ha", (int) BFD_RELOC_PPC_GOT_TLSGD16_HA),
+ MAP ("got@tlsld", (int) BFD_RELOC_PPC_GOT_TLSLD16),
+ MAP ("got@tlsld@l", (int) BFD_RELOC_PPC_GOT_TLSLD16_LO),
+ MAP ("got@tlsld@h", (int) BFD_RELOC_PPC_GOT_TLSLD16_HI),
+ MAP ("got@tlsld@ha", (int) BFD_RELOC_PPC_GOT_TLSLD16_HA),
+ MAP ("got@dtprel", (int) BFD_RELOC_PPC_GOT_DTPREL16),
+ MAP ("got@dtprel@l", (int) BFD_RELOC_PPC_GOT_DTPREL16_LO),
+ MAP ("got@dtprel@h", (int) BFD_RELOC_PPC_GOT_DTPREL16_HI),
+ MAP ("got@dtprel@ha", (int) BFD_RELOC_PPC_GOT_DTPREL16_HA),
+ MAP ("got@tprel", (int) BFD_RELOC_PPC_GOT_TPREL16),
+ MAP ("got@tprel@l", (int) BFD_RELOC_PPC_GOT_TPREL16_LO),
+ MAP ("got@tprel@h", (int) BFD_RELOC_PPC_GOT_TPREL16_HI),
+ MAP ("got@tprel@ha", (int) BFD_RELOC_PPC_GOT_TPREL16_HA),
/* The following are only valid for ppc64. Negative values are
used instead of a flag. */
- MAP ("higher", - (int) BFD_RELOC_PPC64_HIGHER),
- MAP ("highera", - (int) BFD_RELOC_PPC64_HIGHER_S),
- MAP ("highest", - (int) BFD_RELOC_PPC64_HIGHEST),
- MAP ("highesta", - (int) BFD_RELOC_PPC64_HIGHEST_S),
- MAP ("tocbase", - (int) BFD_RELOC_PPC64_TOC),
- MAP ("toc", - (int) BFD_RELOC_PPC_TOC16),
- MAP ("toc@l", - (int) BFD_RELOC_PPC64_TOC16_LO),
- MAP ("toc@h", - (int) BFD_RELOC_PPC64_TOC16_HI),
- MAP ("toc@ha", - (int) BFD_RELOC_PPC64_TOC16_HA),
- { (char *) 0, 0, (int) BFD_RELOC_UNUSED }
+ MAP ("higher", - (int) BFD_RELOC_PPC64_HIGHER),
+ MAP ("highera", - (int) BFD_RELOC_PPC64_HIGHER_S),
+ MAP ("highest", - (int) BFD_RELOC_PPC64_HIGHEST),
+ MAP ("highesta", - (int) BFD_RELOC_PPC64_HIGHEST_S),
+ MAP ("tocbase", - (int) BFD_RELOC_PPC64_TOC),
+ MAP ("toc", - (int) BFD_RELOC_PPC_TOC16),
+ MAP ("toc@l", - (int) BFD_RELOC_PPC64_TOC16_LO),
+ MAP ("toc@h", - (int) BFD_RELOC_PPC64_TOC16_HI),
+ MAP ("toc@ha", - (int) BFD_RELOC_PPC64_TOC16_HA),
+ MAP ("dtprel@higher", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHER),
+ MAP ("dtprel@highera", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHERA),
+ MAP ("dtprel@highest", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHEST),
+ MAP ("dtprel@highesta", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHESTA),
+ MAP ("tprel@higher", - (int) BFD_RELOC_PPC64_TPREL16_HIGHER),
+ MAP ("tprel@highera", - (int) BFD_RELOC_PPC64_TPREL16_HIGHERA),
+ MAP ("tprel@highest", - (int) BFD_RELOC_PPC64_TPREL16_HIGHEST),
+ MAP ("tprel@highesta", - (int) BFD_RELOC_PPC64_TPREL16_HIGHESTA),
+ { (char *) 0, 0, (int) BFD_RELOC_UNUSED }
};
if (*str++ != '@')
reloc = -reloc;
}
- 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)
+ 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"));
/* Now check for identifier@suffix+constant. */
if (*str == '-' || *str == '+')
*str_p = str;
if (reloc == (int) BFD_RELOC_PPC64_TOC
- && exp_p->X_op == O_symbol)
+ && exp_p->X_op == O_symbol
+ && strcmp (S_GET_NAME (exp_p->X_add_symbol), ".TOC.") == 0)
{
- /* This reloc type ignores the symbol. Change the symbol
- so that the dummy .TOC. symbol can be omitted from the
- object file. */
+ /* Change the symbol so that the dummy .TOC. symbol can be
+ omitted from the object file. */
exp_p->X_add_symbol = &abs_symbol;
}
for (i = 0; i < ppc_apuinfo_num; i++)
if (ppc_apuinfo_list[i] == APUID (apu, version))
return;
-
+
if (ppc_apuinfo_num == ppc_apuinfo_num_alloc)
{
if (ppc_apuinfo_num_alloc == 0)
if (! register_name (&ex))
{
if ((operand->flags & PPC_OPERAND_CR) != 0)
- cr_operand = true;
+ cr_operand = TRUE;
expression (&ex);
- cr_operand = false;
+ cr_operand = FALSE;
}
}
#ifdef OBJ_ELF
else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
{
+ /* Some TLS tweaks. */
+ switch (reloc)
+ {
+ 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;
+ }
+
/* For the absolute forms of branches, convert the PC
relative form back into the absolute. */
if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
}
if (ppc_obj64
- && (operand->flags & PPC_OPERAND_DS) != 0)
+ && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
{
switch (reloc)
{
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;
{
/* These are all version "1". */
if (opcode->flags & PPC_OPCODE_SPE)
- ppc_apuinfo_section_add (PPC_APUINFO_SPE, 1);
+ ppc_apuinfo_section_add (PPC_APUINFO_SPE, 1);
if (opcode->flags & PPC_OPCODE_ISEL)
- ppc_apuinfo_section_add (PPC_APUINFO_ISEL, 1);
+ ppc_apuinfo_section_add (PPC_APUINFO_ISEL, 1);
if (opcode->flags & PPC_OPCODE_EFS)
- ppc_apuinfo_section_add (PPC_APUINFO_EFS, 1);
+ ppc_apuinfo_section_add (PPC_APUINFO_EFS, 1);
if (opcode->flags & PPC_OPCODE_BRLOCK)
- ppc_apuinfo_section_add (PPC_APUINFO_BRLOCK, 1);
+ ppc_apuinfo_section_add (PPC_APUINFO_BRLOCK, 1);
if (opcode->flags & PPC_OPCODE_PMR)
- ppc_apuinfo_section_add (PPC_APUINFO_PMR, 1);
+ ppc_apuinfo_section_add (PPC_APUINFO_PMR, 1);
if (opcode->flags & PPC_OPCODE_CACHELCK)
- ppc_apuinfo_section_add (PPC_APUINFO_CACHELCK, 1);
+ ppc_apuinfo_section_add (PPC_APUINFO_CACHELCK, 1);
if (opcode->flags & PPC_OPCODE_RFMCI)
- ppc_apuinfo_section_add (PPC_APUINFO_RFMCI, 1);
+ ppc_apuinfo_section_add (PPC_APUINFO_RFMCI, 1);
}
#endif
return SHF_EXCLUDE;
*ptr_msg = _("Bad .section directive: want a,e,w,x,M,S,G,T in string");
- return 0;
+ return -1;
}
int
/* This is set if we are creating a .stabx symbol, since we don't want
to handle symbol suffixes for such symbols. */
-static boolean ppc_stab_symbol;
+static bfd_boolean ppc_stab_symbol;
/* The .comm and .lcomm pseudo-ops for XCOFF. XCOFF puts common
symbols in the .bss segment as though they were local common
char *name;
char endc;
symbolS *sym;
+ offsetT align;
name = input_line_pointer;
endc = get_symbol_end ();
symbol_get_tc (sym)->class = XMC_PR;
}
- ppc_change_csect (sym);
-
+ align = 2;
if (*input_line_pointer == ',')
{
++input_line_pointer;
- symbol_get_tc (sym)->align = get_absolute_expression ();
+ align = get_absolute_expression ();
}
+ ppc_change_csect (sym, align);
+
demand_empty_rest_of_line ();
}
/* Change to a different csect. */
static void
-ppc_change_csect (sym)
+ppc_change_csect (sym, align)
symbolS *sym;
+ offsetT align;
{
if (S_IS_DEFINED (sym))
subseg_set (S_GET_SEGMENT (sym), symbol_get_tc (sym)->subseg);
int after_toc;
int hold_chunksize;
symbolS *list;
+ int is_code;
+ segT sec;
/* This is a new csect. We need to look at the symbol class to
figure out whether it should go in the text section or the
data section. */
after_toc = 0;
+ is_code = 0;
switch (symbol_get_tc (sym)->class)
{
case XMC_PR:
symbol_get_tc (sym)->subseg = ppc_text_subsegment;
++ppc_text_subsegment;
list_ptr = &ppc_text_csects;
+ is_code = 1;
break;
case XMC_RW:
case XMC_TC0:
hold_chunksize = chunksize;
chunksize = 64;
- subseg_new (segment_name (S_GET_SEGMENT (sym)),
- symbol_get_tc (sym)->subseg);
+ sec = subseg_new (segment_name (S_GET_SEGMENT (sym)),
+ symbol_get_tc (sym)->subseg);
chunksize = hold_chunksize;
if (after_toc)
ppc_after_toc_frag = frag_now;
+ record_alignment (sec, align);
+ if (is_code)
+ frag_align_code (align, 0);
+ else
+ frag_align (align, 0, 0);
+
symbol_set_frag (sym, frag_now);
S_SET_VALUE (sym, (valueT) frag_now_fix ());
- symbol_get_tc (sym)->align = 2;
+ symbol_get_tc (sym)->align = align;
symbol_get_tc (sym)->output = 1;
symbol_get_tc (sym)->within = sym;
sym = symbol_find_or_make (name);
- ppc_change_csect (sym);
+ ppc_change_csect (sym, 2);
demand_empty_rest_of_line ();
}
sym = symbol_find_or_make (real_name);
- ppc_change_csect (sym);
+ ppc_change_csect (sym, 2);
demand_empty_rest_of_line ();
}
}
++input_line_pointer;
- ppc_stab_symbol = true;
+ ppc_stab_symbol = TRUE;
sym = symbol_make (name);
- ppc_stab_symbol = false;
+ ppc_stab_symbol = FALSE;
symbol_get_tc (sym)->real_name = name;
give to this location in the toc; this will be a symbol with class
TC. The rest of the arguments are N-byte values to actually put at
this location in the TOC; often there is just one more argument, a
- relocateable symbol reference. The size of the value to store
+ relocatable symbol reference. The size of the value to store
depends on target word size. A 32-bit target uses 4-byte values, a
64-bit target uses 8-byte values.
/* pseudo-op: .pdata
behaviour: predefined read only data section
- double word aligned
+ double word aligned
errors: None
warnings: None
initial: .section .pdata "adr3"
- a - don't know -- maybe a misprint
+ a - don't know -- maybe a misprint
d - initialized data
r - readable
3 - double word aligned (that would be 4 byte boundary)
/* pseudo-op: .ydata
behaviour: predefined read only data section
- double word aligned
+ double word aligned
errors: None
warnings: None
initial: .section .ydata "drw3"
- a - don't know -- maybe a misprint
+ a - don't know -- maybe a misprint
d - initialized data
r - readable
3 - double word aligned (that would be 4 byte boundary)
/* pseudo-op: .reldata
behaviour: predefined read write data section
- double word aligned (4-byte)
+ double word aligned (4-byte)
FIXME: relocation is applied to it
FIXME: what's the difference between this and .data?
errors: None
/* pseudo-op: .rdata
behaviour: predefined read only data section
- double word aligned
+ double word aligned
errors: None
warnings: None
initial: .section .rdata "dr3"
/* pseudo-op: .ualong
behaviour: much like .int, with the exception that no alignment is
- performed.
+ performed.
FIXME: test the alignment statement
errors: None
warnings: None */
/* pseudo-op: .znop <symbol name>
behaviour: Issue a nop instruction
- Issue a IMAGE_REL_PPC_IFGLUE relocation against it, using
+ Issue a IMAGE_REL_PPC_IFGLUE relocation against it, using
the supplied symbol name.
errors: None
warnings: Missing symbol name */
seen. It tells ppc_adjust_symtab whether it needs to look through
the symbols. */
-static boolean ppc_saw_abs;
+static bfd_boolean ppc_saw_abs;
/* Change the name of a symbol just before writing it out. Set the
real name if the .rename pseudo-op was used. Otherwise, remove any
{
/* This is an absolute symbol. The csect will be created by
ppc_adjust_symtab. */
- ppc_saw_abs = true;
+ 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;
coffsymbol (symbol_get_bfdsym (sym))->native[i].fix_scnlen = 1;
}
- ppc_saw_abs = false;
+ ppc_saw_abs = FALSE;
}
/* Set the VMA for a section. This is called on all the sections in
ppc_frob_section (sec)
asection *sec;
{
- static bfd_size_type vma = 0;
+ static bfd_vma vma = 0;
+ vma = md_section_align (sec, vma);
bfd_set_section_vma (stdoutput, sec, vma);
vma += bfd_section_size (stdoutput, sec);
}
<= fix->fx_frag->fr_address))))
return 1;
- return S_FORCE_RELOC (fix->fx_addsy);
+ return generic_force_reloc (fix);
}
#endif /* OBJ_XCOFF */
case BFD_RELOC_PPC_BA16_BRTAKEN:
case BFD_RELOC_PPC_BA16_BRNTAKEN:
case BFD_RELOC_PPC64_TOC:
- case BFD_RELOC_VTABLE_INHERIT:
- case BFD_RELOC_VTABLE_ENTRY:
return 1;
default:
break;
}
- return S_FORCE_RELOC (fix->fx_addsy);
+ if (fix->fx_r_type >= BFD_RELOC_PPC_TLS
+ && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA)
+ return 1;
+
+ return generic_force_reloc (fix);
}
int
&& fix->fx_r_type != BFD_RELOC_GPREL16
&& fix->fx_r_type != BFD_RELOC_VTABLE_INHERIT
&& fix->fx_r_type != BFD_RELOC_VTABLE_ENTRY
+ && !(fix->fx_r_type >= BFD_RELOC_PPC_TLS
+ && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA)
&& (fix->fx_pcrel
|| (fix->fx_subsy != NULL
&& (S_GET_SEGMENT (fix->fx_subsy)
#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))
+ && operand->shift == 0)
{
- fixP->fx_r_type = BFD_RELOC_PPC_TOC16;
+ if (ppc_is_toc_sym (fixP->fx_addsy))
+ {
+ fixP->fx_r_type = BFD_RELOC_PPC_TOC16;
#ifdef OBJ_ELF
- if (ppc_obj64
- && (operand->flags & PPC_OPERAND_DS) != 0)
- fixP->fx_r_type = BFD_RELOC_PPC64_TOC16_DS;
+ if (ppc_obj64
+ && (operand->flags & PPC_OPERAND_DS) != 0)
+ fixP->fx_r_type = BFD_RELOC_PPC64_TOC16_DS;
#endif
+ }
+ else
+ {
+ fixP->fx_r_type = BFD_RELOC_16;
+#ifdef OBJ_ELF
+ if (ppc_obj64
+ && (operand->flags & PPC_OPERAND_DS) != 0)
+ fixP->fx_r_type = BFD_RELOC_PPC64_ADDR16_DS;
+#endif
+ }
fixP->fx_size = 2;
if (target_big_endian)
fixP->fx_where += 2;
abort ();
{
unsigned char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
- unsigned long val;
+ unsigned long val, mask;
if (target_big_endian)
- val = bfd_getb16 (where);
+ val = bfd_getb32 (where - 2);
else
- val = bfd_getl16 (where);
- val |= (value & 0xfffc);
+ val = bfd_getl32 (where);
+ mask = 0xfffc;
+ /* lq insns reserve the four lsbs. */
+ if ((ppc_cpu & PPC_OPCODE_POWER4) != 0
+ && (val & (0x3f << 26)) == (56u << 26))
+ mask = 0xfff0;
+ val |= value & mask;
if (target_big_endian)
bfd_putb16 ((bfd_vma) val, where);
else
bfd_putl16 ((bfd_vma) val, where);
}
break;
+
+ case BFD_RELOC_PPC_B16_BRTAKEN:
+ case BFD_RELOC_PPC_B16_BRNTAKEN:
+ case BFD_RELOC_PPC_BA16_BRTAKEN:
+ case BFD_RELOC_PPC_BA16_BRNTAKEN:
+ break;
+
+ case BFD_RELOC_PPC_TLS:
+ case BFD_RELOC_PPC_DTPMOD:
+ case BFD_RELOC_PPC_TPREL16:
+ case BFD_RELOC_PPC_TPREL16_LO:
+ case BFD_RELOC_PPC_TPREL16_HI:
+ case BFD_RELOC_PPC_TPREL16_HA:
+ case BFD_RELOC_PPC_TPREL:
+ case BFD_RELOC_PPC_DTPREL16:
+ case BFD_RELOC_PPC_DTPREL16_LO:
+ case BFD_RELOC_PPC_DTPREL16_HI:
+ case BFD_RELOC_PPC_DTPREL16_HA:
+ case BFD_RELOC_PPC_DTPREL:
+ 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_TPREL16:
+ case BFD_RELOC_PPC_GOT_TPREL16_LO:
+ case BFD_RELOC_PPC_GOT_TPREL16_HI:
+ case BFD_RELOC_PPC_GOT_TPREL16_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_PPC64_TPREL16_DS:
+ case BFD_RELOC_PPC64_TPREL16_LO_DS:
+ case BFD_RELOC_PPC64_TPREL16_HIGHER:
+ case BFD_RELOC_PPC64_TPREL16_HIGHERA:
+ case BFD_RELOC_PPC64_TPREL16_HIGHEST:
+ case BFD_RELOC_PPC64_TPREL16_HIGHESTA:
+ case BFD_RELOC_PPC64_DTPREL16_DS:
+ case BFD_RELOC_PPC64_DTPREL16_LO_DS:
+ case BFD_RELOC_PPC64_DTPREL16_HIGHER:
+ case BFD_RELOC_PPC64_DTPREL16_HIGHERA:
+ case BFD_RELOC_PPC64_DTPREL16_HIGHEST:
+ case BFD_RELOC_PPC64_DTPREL16_HIGHESTA:
+ break;
#endif
/* Because SDA21 modifies the register field, the size is set to 4
bytes, rather than 2, so offset it here appropriately. */
return reloc;
}
+
+void
+ppc_cfi_frame_initial_instructions ()
+{
+ cfi_add_CFA_def_cfa (1, 0);
+}
+
+int
+tc_ppc_regname_to_dw2regnum (const char *regname)
+{
+ unsigned int regnum = -1;
+ unsigned int i;
+ const char *p;
+ char *q;
+ static struct { char *name; int dw2regnum; } regnames[] =
+ {
+ { "sp", 1 }, { "r.sp", 1 }, { "rtoc", 2 }, { "r.toc", 2 },
+ { "mq", 64 }, { "lr", 65 }, { "ctr", 66 }, { "ap", 67 },
+ { "cc", 68 }, { "xer", 76 }, { "vrsave", 109 }, { "vscr", 110 },
+ { "spe_acc", 111 }, { "spefscr", 112 }
+ };
+
+ for (i = 0; i < ARRAY_SIZE (regnames); ++i)
+ if (strcmp (regnames[i].name, regname) == 0)
+ return regnames[i].dw2regnum;
+
+ if (regname[0] == 'r' || regname[0] == 'f' || regname[0] == 'v')
+ {
+ p = regname + 1 + (regname[1] == '.');
+ regnum = strtoul (p, &q, 10);
+ if (p == q || *q || regnum >= 32)
+ return -1;
+ if (regname[0] == 'f')
+ regnum += 32;
+ else if (regname[0] == 'v')
+ regnum += 77;
+ }
+ else if (regname[0] == 'c' && regname[1] == 'r')
+ {
+ p = regname + 2 + (regname[2] == '.');
+ if (p[0] < '0' || p[0] > '7' || p[1])
+ return -1;
+ regnum = p[0] - '0' + 68;
+ }
+ return regnum;
+}