X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-ppc.c;h=5849654837a318f3b8a8b89323d4404219f9acc4;hb=b256d4fdd25ed91f9d5edcdd23d3558b4cbca71b;hp=613a61a203c80f4265ce3db9ae1439aeb554cae1;hpb=a161fe53205dbc69d42f5a123b2b04346724b2de;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 613a61a203..5849654837 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -1,5 +1,5 @@ /* 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. @@ -24,7 +24,7 @@ #include "as.h" #include "safe-ctype.h" #include "subsegs.h" - +#include "dw2gencfi.h" #include "opcode/ppc.h" #ifdef OBJ_ELF @@ -47,9 +47,9 @@ static int set_target_endian = 0; /* 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 @@ -83,9 +83,9 @@ static int set_target_endian = 0; #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, @@ -111,7 +111,7 @@ 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 *)); +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)); @@ -182,6 +182,13 @@ const char EXP_CHARS[] = "eE"; /* 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; /* The target specific pseudo-ops which we support. */ @@ -233,8 +240,6 @@ const pseudo_typeS md_pseudo_table[] = { "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 @@ -603,7 +608,7 @@ reg_name_search (regs, regcount, name) * original state. */ -static boolean +static bfd_boolean register_name (expressionP) expressionS *expressionP; { @@ -618,7 +623,7 @@ register_name (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); @@ -635,12 +640,12 @@ register_name (expressionP) /* 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; } /* This function is called for each symbol seen in an expression. It @@ -648,7 +653,7 @@ register_name (expressionP) 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[] = @@ -716,12 +721,12 @@ static flagword ppc_flags = 0; /* 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 @@ -796,8 +801,8 @@ symbolS *GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE" */ #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; @@ -891,8 +896,8 @@ md_parse_option (c, arg) /* -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 @@ -902,28 +907,32 @@ md_parse_option (c, arg) 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) @@ -939,8 +948,8 @@ md_parse_option (c, arg) } 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) @@ -950,13 +959,13 @@ md_parse_option (c, arg) /* -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 @@ -965,13 +974,13 @@ md_parse_option (c, arg) 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 @@ -1008,13 +1017,13 @@ md_parse_option (c, arg) 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 @@ -1059,36 +1068,41 @@ md_show_usage (stream) { 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\ @@ -1104,24 +1118,24 @@ ppc_set_cpu () 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); @@ -1197,10 +1211,12 @@ md_begin () 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) @@ -1244,11 +1260,15 @@ md_begin () 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 (); @@ -1263,7 +1283,7 @@ md_begin () if (retval != (const char *) NULL) { as_bad (_("Internal assembler error for macro %s"), macro->name); - dup_insn = true; + dup_insn = TRUE; } } } @@ -1323,19 +1343,19 @@ ppc_cleanup () 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); @@ -1345,8 +1365,8 @@ ppc_cleanup () 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); @@ -1459,60 +1479,94 @@ ppc_elf_suffix (str_p, exp_p) #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++ != '@') @@ -1544,12 +1598,13 @@ ppc_elf_suffix (str_p, exp_p) 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 == '+') @@ -1571,11 +1626,11 @@ ppc_elf_suffix (str_p, exp_p) *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; } @@ -1968,7 +2023,7 @@ ppc_apuinfo_section_add (apu, version) 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) @@ -2069,6 +2124,8 @@ md_assemble (str) if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0) { 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. */ @@ -2085,10 +2142,16 @@ md_assemble (str) } } + /* Compute the number of expected operands. + Do not count fake operands. */ + for (num_operands_expected = 0, i = 0; opcode->operands[i]; i ++) + if ((powerpc_operands [opcode->operands[i]].flags & PPC_OPERAND_FAKE) == 0) + ++ num_operands_expected; + /* If there are fewer operands in the line then are called for by the instruction, we want to skip the optional operand. */ - if (opcount < strlen (opcode->operands)) + if (opcount < num_operands_expected) skip_optional = 1; break; @@ -2264,9 +2327,9 @@ md_assemble (str) 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; } } @@ -2354,6 +2417,25 @@ md_assemble (str) #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) @@ -2378,7 +2460,7 @@ md_assemble (str) } if (ppc_obj64 - && (operand->flags & PPC_OPERAND_DS) != 0) + && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0) { switch (reloc) { @@ -2415,6 +2497,23 @@ md_assemble (str) 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; @@ -2483,19 +2582,19 @@ md_assemble (str) { /* 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 @@ -2666,7 +2765,7 @@ ppc_section_letter (letter, ptr_msg) return SHF_EXCLUDE; *ptr_msg = _("Bad .section directive: want a,e,w,x,M,S,G,T in string"); - return 0; + return -1; } int @@ -2751,7 +2850,7 @@ ppc_byte (ignore) /* 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 @@ -2920,6 +3019,7 @@ ppc_csect (ignore) char *name; char endc; symbolS *sym; + offsetT align; name = input_line_pointer; endc = get_symbol_end (); @@ -2934,22 +3034,24 @@ ppc_csect (ignore) 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); @@ -2959,11 +3061,14 @@ ppc_change_csect (sym) 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: @@ -2978,6 +3083,7 @@ ppc_change_csect (sym) 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: @@ -3005,18 +3111,24 @@ ppc_change_csect (sym) 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; @@ -3054,7 +3166,7 @@ ppc_section (type) sym = symbol_find_or_make (name); - ppc_change_csect (sym); + ppc_change_csect (sym, 2); demand_empty_rest_of_line (); } @@ -3091,7 +3203,7 @@ ppc_named_section (ignore) sym = symbol_find_or_make (real_name); - ppc_change_csect (sym); + ppc_change_csect (sym, 2); demand_empty_rest_of_line (); } @@ -3194,9 +3306,9 @@ ppc_stabx (ignore) } ++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; @@ -3762,7 +3874,7 @@ ppc_vbyte (dummy) 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. @@ -3925,11 +4037,11 @@ ppc_previous (ignore) /* 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) @@ -3961,11 +4073,11 @@ ppc_pdata (ignore) /* 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) @@ -3995,7 +4107,7 @@ ppc_ydata (ignore) /* 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 @@ -4033,7 +4145,7 @@ ppc_reldata (ignore) /* pseudo-op: .rdata behaviour: predefined read only data section - double word aligned + double word aligned errors: None warnings: None initial: .section .rdata "dr3" @@ -4063,7 +4175,7 @@ ppc_rdata (ignore) /* 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 */ @@ -4078,7 +4190,7 @@ ppc_ualong (ignore) /* pseudo-op: .znop 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 */ @@ -4640,7 +4752,7 @@ ppc_frob_label (sym) 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 @@ -4783,7 +4895,7 @@ ppc_frob_symbol (sym) { /* 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; @@ -4951,7 +5063,7 @@ ppc_adjust_symtab () 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 @@ -4961,8 +5073,9 @@ void 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); } @@ -5247,7 +5360,7 @@ ppc_force_relocation (fix) <= fix->fx_frag->fr_address)))) return 1; - return S_FORCE_RELOC (fix->fx_addsy); + return generic_force_reloc (fix); } #endif /* OBJ_XCOFF */ @@ -5269,14 +5382,16 @@ ppc_force_relocation (fix) 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 @@ -5290,6 +5405,8 @@ ppc_fix_adjustable (fix) && 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) @@ -5438,15 +5555,26 @@ md_apply_fix3 (fixP, valP, seg) #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; @@ -5613,19 +5741,72 @@ md_apply_fix3 (fixP, valP, seg) 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. */ @@ -5751,3 +5932,49 @@ tc_gen_reloc (seg, fixp) 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; +}