X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-ppc.c;h=f054756c042656923f018b41f57606c555e70a9d;hb=01efc3af7b9d3b0bfb9d1d8a748aad1102a810bc;hp=b0c136c6e25f9aea3972d20e66298a7bb75c6fc1;hpb=4e6935a6475f5041952c15c84c7d363fb98f055f;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index b0c136c6e2..f054756c04 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -1,13 +1,13 @@ /* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000) Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005 Free Software Foundation, Inc. + 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. GAS is distributed in the hope that it will be useful, @@ -20,7 +20,6 @@ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -#include #include "as.h" #include "safe-ctype.h" #include "subsegs.h" @@ -85,67 +84,58 @@ static int set_target_endian = 0; static bfd_boolean reg_names_p = TARGET_REG_NAMES_P; -static bfd_boolean register_name PARAMS ((expressionS *)); -static void ppc_set_cpu PARAMS ((void)); -static unsigned long ppc_insert_operand - PARAMS ((unsigned long insn, const struct powerpc_operand *operand, - offsetT val, char *file, unsigned int line)); -static void ppc_macro PARAMS ((char *str, const struct powerpc_macro *macro)); -static void ppc_byte PARAMS ((int)); +static void ppc_macro (char *, const struct powerpc_macro *); +static void ppc_byte (int); #if defined (OBJ_XCOFF) || defined (OBJ_ELF) -static int ppc_is_toc_sym PARAMS ((symbolS *sym)); -static void ppc_tc PARAMS ((int)); -static void ppc_machine PARAMS ((int)); +static void ppc_tc (int); +static void ppc_machine (int); #endif #ifdef OBJ_XCOFF -static void ppc_comm PARAMS ((int)); -static void ppc_bb PARAMS ((int)); -static void ppc_bc PARAMS ((int)); -static void ppc_bf PARAMS ((int)); -static void ppc_biei PARAMS ((int)); -static void ppc_bs PARAMS ((int)); -static void ppc_eb PARAMS ((int)); -static void ppc_ec PARAMS ((int)); -static void ppc_ef PARAMS ((int)); -static void ppc_es PARAMS ((int)); -static void ppc_csect PARAMS ((int)); -static void ppc_change_csect PARAMS ((symbolS *, offsetT)); -static void ppc_function PARAMS ((int)); -static void ppc_extern PARAMS ((int)); -static void ppc_lglobl PARAMS ((int)); -static void ppc_section PARAMS ((int)); -static void ppc_named_section PARAMS ((int)); -static void ppc_stabx PARAMS ((int)); -static void ppc_rename PARAMS ((int)); -static void ppc_toc PARAMS ((int)); -static void ppc_xcoff_cons PARAMS ((int)); -static void ppc_vbyte PARAMS ((int)); +static void ppc_comm (int); +static void ppc_bb (int); +static void ppc_bc (int); +static void ppc_bf (int); +static void ppc_biei (int); +static void ppc_bs (int); +static void ppc_eb (int); +static void ppc_ec (int); +static void ppc_ef (int); +static void ppc_es (int); +static void ppc_csect (int); +static void ppc_change_csect (symbolS *, offsetT); +static void ppc_function (int); +static void ppc_extern (int); +static void ppc_lglobl (int); +static void ppc_ref (int); +static void ppc_section (int); +static void ppc_named_section (int); +static void ppc_stabx (int); +static void ppc_rename (int); +static void ppc_toc (int); +static void ppc_xcoff_cons (int); +static void ppc_vbyte (int); #endif #ifdef OBJ_ELF -static bfd_reloc_code_real_type ppc_elf_suffix PARAMS ((char **, expressionS *)); -static void ppc_elf_cons PARAMS ((int)); -static void ppc_elf_rdata PARAMS ((int)); -static void ppc_elf_lcomm PARAMS ((int)); -static void ppc_elf_validate_fix PARAMS ((fixS *, segT)); -static void ppc_apuinfo_section_add PARAMS ((unsigned int apu, unsigned int version)); +static void ppc_elf_cons (int); +static void ppc_elf_rdata (int); +static void ppc_elf_lcomm (int); #endif #ifdef TE_PE -static void ppc_set_current_section PARAMS ((segT)); -static void ppc_previous PARAMS ((int)); -static void ppc_pdata PARAMS ((int)); -static void ppc_ydata PARAMS ((int)); -static void ppc_reldata PARAMS ((int)); -static void ppc_rdata PARAMS ((int)); -static void ppc_ualong PARAMS ((int)); -static void ppc_znop PARAMS ((int)); -static void ppc_pe_comm PARAMS ((int)); -static void ppc_pe_section PARAMS ((int)); -static void ppc_pe_function PARAMS ((int)); -static void ppc_pe_tocd PARAMS ((int)); +static void ppc_previous (int); +static void ppc_pdata (int); +static void ppc_ydata (int); +static void ppc_reldata (int); +static void ppc_rdata (int); +static void ppc_ualong (int); +static void ppc_znop (int); +static void ppc_pe_comm (int); +static void ppc_pe_section (int); +static void ppc_pe_function (int); +static void ppc_pe_tocd (int); #endif /* Generic assembler global variables which must be defined by all @@ -183,12 +173,22 @@ const char EXP_CHARS[] = "eE"; 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[] = "+-"; +/* Anything that can start an operand needs to be mentioned here, + to stop the input scrubber eating whitespace. */ +const char ppc_symbol_chars[] = "%["; /* The dwarf2 data alignment, adjusted for 32 or 64 bit. */ int ppc_cie_data_alignment; + +/* The type of processor we are assembling for. This is one or more + of the PPC_OPCODE flags defined in opcode/ppc.h. */ +ppc_cpu_t ppc_cpu = 0; + +/* Flags set on encountering toc relocs. */ +enum { + has_large_toc_reloc = 1, + has_small_toc_reloc = 2 +} toc_reloc_types; /* The target specific pseudo-ops which we support. */ @@ -219,6 +219,7 @@ const pseudo_typeS md_pseudo_table[] = { "extern", ppc_extern, 0 }, { "function", ppc_function, 0 }, { "lglobl", ppc_lglobl, 0 }, + { "ref", ppc_ref, 0 }, { "rename", ppc_rename, 0 }, { "section", ppc_named_section, 0 }, { "stabx", ppc_stabx, 0 }, @@ -365,9 +366,42 @@ static const struct pd_reg pre_defined_registers[] = { "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 }, @@ -398,15 +432,66 @@ static const struct pd_reg pre_defined_registers[] = { "f3", 3 }, { "f30", 30 }, { "f31", 31 }, + + { "f32", 32 }, /* Extended floating point scalar registers (ISA 2.06). */ + { "f33", 33 }, + { "f34", 34 }, + { "f35", 35 }, + { "f36", 36 }, + { "f37", 37 }, + { "f38", 38 }, + { "f39", 39 }, { "f4", 4 }, + { "f40", 40 }, + { "f41", 41 }, + { "f42", 42 }, + { "f43", 43 }, + { "f44", 44 }, + { "f45", 45 }, + { "f46", 46 }, + { "f47", 47 }, + { "f48", 48 }, + { "f49", 49 }, { "f5", 5 }, + { "f50", 50 }, + { "f51", 51 }, + { "f52", 52 }, + { "f53", 53 }, + { "f54", 54 }, + { "f55", 55 }, + { "f56", 56 }, + { "f57", 57 }, + { "f58", 58 }, + { "f59", 59 }, { "f6", 6 }, + { "f60", 60 }, + { "f61", 61 }, + { "f62", 62 }, + { "f63", 63 }, { "f7", 7 }, { "f8", 8 }, { "f9", 9 }, { "fpscr", 0 }, + /* Quantization registers used with pair single instructions. */ + { "gqr.0", 0 }, + { "gqr.1", 1 }, + { "gqr.2", 2 }, + { "gqr.3", 3 }, + { "gqr.4", 4 }, + { "gqr.5", 5 }, + { "gqr.6", 6 }, + { "gqr.7", 7 }, + { "gqr0", 0 }, + { "gqr1", 1 }, + { "gqr2", 2 }, + { "gqr3", 3 }, + { "gqr4", 4 }, + { "gqr5", 5 }, + { "gqr6", 6 }, + { "gqr7", 7 }, + { "lr", 8 }, /* Link Register */ { "pmr", 0 }, @@ -490,7 +575,7 @@ static const struct pd_reg pre_defined_registers[] = { "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 }, @@ -556,6 +641,136 @@ static const struct pd_reg pre_defined_registers[] = { "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 }, }; @@ -565,14 +780,8 @@ static const struct pd_reg pre_defined_registers[] = /* Given NAME, find the register number associated with that name, return the integer value associated with the given name or -1 on failure. */ -static int reg_name_search - PARAMS ((const struct pd_reg *, int, const char * name)); - static int -reg_name_search (regs, regcount, name) - const struct pd_reg *regs; - int regcount; - const char *name; +reg_name_search (const struct pd_reg *regs, int regcount, const char *name) { int middle, low, high; int cmp; @@ -609,8 +818,7 @@ reg_name_search (regs, regcount, name) */ static bfd_boolean -register_name (expressionP) - expressionS *expressionP; +register_name (expressionS *expressionP) { int reg_number; char *name; @@ -677,32 +885,28 @@ static const struct pd_reg cr_names[] = expression. */ int -ppc_parse_name (name, expr) - const char *name; - expressionS *expr; +ppc_parse_name (const char *name, expressionS *exp) { int val; if (! cr_operand) return 0; + if (*name == '%') + ++name; val = reg_name_search (cr_names, sizeof cr_names / sizeof cr_names[0], name); if (val < 0) return 0; - expr->X_op = O_constant; - expr->X_add_number = val; + exp->X_op = O_constant; + exp->X_add_number = val; return 1; } /* Local variables. */ -/* The type of processor we are assembling for. This is one or more - of the PPC_OPCODE flags defined in opcode/ppc.h. */ -static unsigned long ppc_cpu = 0; - /* Whether to target xcoff64/elf64. */ static unsigned int ppc_obj64 = BFD_DEFAULT_TARGET_SIZE == 64; @@ -819,118 +1023,11 @@ const struct option md_longopts[] = { }; const size_t md_longopts_size = sizeof (md_longopts); - -/* Handle -m options that set cpu type, and .machine arg. */ - -static int -parse_cpu (const char *arg) -{ - /* -mpwrx and -mpwr2 mean to assemble for the IBM POWER/2 - (RIOS2). */ - if (strcmp (arg, "pwrx") == 0 || strcmp (arg, "pwr2") == 0) - ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_32; - /* -mpwr means to assemble for the IBM POWER (RIOS1). */ - else if (strcmp (arg, "pwr") == 0) - ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32; - /* -m601 means to assemble for the PowerPC 601, which includes - instructions that are holdovers from the Power. */ - else if (strcmp (arg, "601") == 0) - ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC - | PPC_OPCODE_601 | PPC_OPCODE_32); - /* -mppc, -mppc32, -m603, and -m604 mean to assemble for the - PowerPC 603/604. */ - else if (strcmp (arg, "ppc") == 0 - || strcmp (arg, "ppc32") == 0 - || strcmp (arg, "603") == 0 - || strcmp (arg, "604") == 0) - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32; - /* -m403 and -m405 mean to assemble for the PowerPC 403/405. */ - else if (strcmp (arg, "403") == 0 - || strcmp (arg, "405") == 0) - ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC - | PPC_OPCODE_403 | PPC_OPCODE_32); - else if (strcmp (arg, "440") == 0) - ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32 - | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI); - else if (strcmp (arg, "7400") == 0 - || strcmp (arg, "7410") == 0 - || strcmp (arg, "7450") == 0 - || strcmp (arg, "7455") == 0) - ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC - | PPC_OPCODE_ALTIVEC | PPC_OPCODE_32); - else if (strcmp (arg, "altivec") == 0) - { - if (ppc_cpu == 0) - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC; - else - ppc_cpu |= PPC_OPCODE_ALTIVEC; - } - else if (strcmp (arg, "e500") == 0 || strcmp (arg, "e500x2") == 0) - { - ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE - | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK - | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK - | PPC_OPCODE_RFMCI); - } - else if (strcmp (arg, "spe") == 0) - { - if (ppc_cpu == 0) - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_SPE | PPC_OPCODE_EFS; - else - ppc_cpu |= PPC_OPCODE_SPE; - } - /* -mppc64 and -m620 mean to assemble for the 64-bit PowerPC - 620. */ - else if (strcmp (arg, "ppc64") == 0 || strcmp (arg, "620") == 0) - { - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64; - } - else if (strcmp (arg, "ppc64bridge") == 0) - { - ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC - | PPC_OPCODE_64_BRIDGE | PPC_OPCODE_64); - } - /* -mbooke/-mbooke32 mean enable 32-bit BookE support. */ - else if (strcmp (arg, "booke") == 0 || strcmp (arg, "booke32") == 0) - { - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32; - } - /* -mbooke64 means enable 64-bit BookE support. */ - else if (strcmp (arg, "booke64") == 0) - { - ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE - | PPC_OPCODE_BOOKE64 | PPC_OPCODE_64); - } - else if (strcmp (arg, "power4") == 0) - { - ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC - | PPC_OPCODE_64 | PPC_OPCODE_POWER4); - } - else if (strcmp (arg, "power5") == 0) - { - ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC - | PPC_OPCODE_64 | PPC_OPCODE_POWER4 - | PPC_OPCODE_POWER5); - } - /* -mcom means assemble for the common intersection between Power - and PowerPC. At present, we just allow the union, rather - than the intersection. */ - else if (strcmp (arg, "com") == 0) - ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32; - /* -many means to assemble for any architecture (PWR/PWRX/PPC). */ - else if (strcmp (arg, "any") == 0) - ppc_cpu |= PPC_OPCODE_ANY; - else - return 0; - - return 1; -} - int -md_parse_option (c, arg) - int c; - char *arg; +md_parse_option (int c, char *arg) { + ppc_cpu_t new_cpu; + switch (c) { case 'u': @@ -993,8 +1090,8 @@ md_parse_option (c, arg) break; case 'm': - if (parse_cpu (arg)) - ; + if ((new_cpu = ppc_parse_cpu (ppc_cpu, arg)) != 0) + ppc_cpu = new_cpu; else if (strcmp (arg, "regnames") == 0) reg_names_p = TRUE; @@ -1083,58 +1180,70 @@ md_parse_option (c, arg) } void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *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\ +-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\ --m440 generate code for PowerPC 440\n\ + generate code for PowerPC 603/604\n\ +-m403 generate code for PowerPC 403\n\ +-m405 generate code for PowerPC 405\n\ +-m440 generate code for PowerPC 440\n\ +-m464 generate code for PowerPC 464\n\ +-m476 generate code for PowerPC 476\n\ -m7400, -m7410, -m7450, -m7455\n\ - generate code For PowerPC 7400/7410/7450/7455\n")); + generate code for PowerPC 7400/7410/7450/7455\n\ +-m750cl generate code for PowerPC 750cl\n")); fprintf (stream, _("\ --mppc64, -m620 generate code for PowerPC 620/625/630\n\ --mppc64bridge generate code for PowerPC 64, including bridge insns\n\ --mbooke64 generate code for 64-bit PowerPC BookE\n\ --mbooke, mbooke32 generate code for 32-bit PowerPC BookE\n\ --mpower4 generate code for Power4 architecture\n\ --mpower5 generate code for Power5 architecture\n\ --mcom generate code Power/PowerPC common instructions\n\ --many generate code for any architecture (PWR/PWRX/PPC)\n")); +-mppc64, -m620 generate code for PowerPC 620/625/630\n\ +-mppc64bridge generate code for PowerPC 64, including bridge insns\n\ +-mbooke generate code for 32-bit PowerPC BookE\n\ +-ma2 generate code for A2 architecture\n\ +-mpower4, -mpwr4 generate code for Power4 architecture\n\ +-mpower5, -mpwr5, -mpwr5x\n\ + generate code for Power5 architecture\n\ +-mpower6, -mpwr6 generate code for Power6 architecture\n\ +-mpower7, -mpwr7 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\ --me500, -me500x2 generate code for Motorola e500 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")); +-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\ +-me500mc64, generate code for Freescale e500mc64 core complex\n\ +-mspe generate code for Motorola SPE instructions\n\ +-mtitan generate code for AppliedMicro Titan core complex\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\ +-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, -l, -le\n\ - generate code for a little endian machine\n\ + generate code for a little 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\ --Qy, -Qn ignored\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\ +-Qy, -Qn ignored\n")); #endif } /* Set ppc_cpu if it is not already set. */ static void -ppc_set_cpu () +ppc_set_cpu (void) { const char *default_os = TARGET_OS; const char *default_cpu = TARGET_CPU; @@ -1151,12 +1260,7 @@ ppc_set_cpu () else if (strcmp (default_cpu, "rs6000") == 0) 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; - } + ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32; else as_fatal (_("Unknown default cpu = %s, os = %s"), default_cpu, default_os); @@ -1167,7 +1271,7 @@ ppc_set_cpu () are called well before md_begin, when the output file is opened. */ enum bfd_architecture -ppc_arch () +ppc_arch (void) { const char *default_cpu = TARGET_CPU; ppc_set_cpu (); @@ -1189,18 +1293,20 @@ ppc_arch () } unsigned long -ppc_mach () +ppc_mach (void) { if (ppc_obj64) return bfd_mach_ppc64; else if (ppc_arch () == bfd_arch_rs6000) return bfd_mach_rs6k; + else if (ppc_cpu & PPC_OPCODE_TITAN) + return bfd_mach_ppc_titan; else return bfd_mach_ppc; } extern char* -ppc_target_format () +ppc_target_format (void) { #ifdef OBJ_COFF #ifdef TE_PE @@ -1232,11 +1338,11 @@ ppc_target_format () static void ppc_setup_opcodes (void) { - register const struct powerpc_opcode *op; + const struct powerpc_opcode *op; const struct powerpc_opcode *op_end; const struct powerpc_macro *macro; const struct powerpc_macro *macro_end; - bfd_boolean dup_insn = FALSE; + bfd_boolean bad_insn = FALSE; if (ppc_hash != NULL) hash_die (ppc_hash); @@ -1246,34 +1352,137 @@ ppc_setup_opcodes (void) /* Insert the opcodes into a hash table. */ ppc_hash = hash_new (); + if (ENABLE_CHECKING) + { + unsigned int i; + + /* Check operand masks. Code here and in the disassembler assumes + all the 1's in the mask are contiguous. */ + for (i = 0; i < num_powerpc_operands; ++i) + { + unsigned long mask = powerpc_operands[i].bitm; + unsigned long right_bit; + unsigned int j; + + right_bit = mask & -mask; + mask += right_bit; + right_bit = mask & -mask; + if (mask != right_bit) + { + as_bad (_("powerpc_operands[%d].bitm invalid"), i); + bad_insn = TRUE; + } + for (j = i + 1; j < num_powerpc_operands; ++j) + if (memcmp (&powerpc_operands[i], &powerpc_operands[j], + sizeof (powerpc_operands[0])) == 0) + { + as_bad (_("powerpc_operands[%d] duplicates powerpc_operands[%d]"), + j, i); + bad_insn = TRUE; + } + } + } + op_end = powerpc_opcodes + powerpc_num_opcodes; for (op = powerpc_opcodes; op < op_end; op++) { - know ((op->opcode & op->mask) == op->opcode); + if (ENABLE_CHECKING) + { + const unsigned char *o; + unsigned long omask = op->mask; + + if (op != powerpc_opcodes) + { + /* The major opcodes had better be sorted. Code in the + disassembler assumes the insns are sorted according to + major opcode. */ + if (PPC_OP (op[0].opcode) < PPC_OP (op[-1].opcode)) + { + as_bad (_("major opcode is not sorted for %s"), + op->name); + bad_insn = TRUE; + } + + /* Warn if the table isn't more strictly ordered. + Unfortunately it doesn't seem possible to order the + table on much more than the major opcode, which makes + it difficult to implement a binary search in the + disassembler. The problem is that we have multiple + ways to disassemble instructions, and we usually want + to choose a more specific form (with more bits set in + the opcode) than a more general form. eg. all of the + following are equivalent: + bne label # opcode = 0x40820000, mask = 0xff830003 + bf 2,label # opcode = 0x40800000, mask = 0xff800003 + bc 4,2,label # opcode = 0x40000000, mask = 0xfc000003 + + There are also cases where the table needs to be out + of order to disassemble the correct instruction for + processor variants. */ + else if (0) + { + unsigned long t1 = op[0].opcode; + unsigned long t2 = op[-1].opcode; + + if (((t1 ^ t2) & 0xfc0007ff) == 0 + && (t1 & 0xfc0006df) == 0x7c000286) + { + /* spr field is split. */ + t1 = ((t1 & ~0x1ff800) + | ((t1 & 0xf800) << 5) | ((t1 & 0x1f0000) >> 5)); + t2 = ((t2 & ~0x1ff800) + | ((t2 & 0xf800) << 5) | ((t2 & 0x1f0000) >> 5)); + } + if (t1 < t2) + as_warn (_("%s (%08lx %08lx) after %s (%08lx %08lx)"), + op[0].name, op[0].opcode, op[0].mask, + op[-1].name, op[-1].opcode, op[-1].mask); + } + } + + /* The mask had better not trim off opcode bits. */ + if ((op->opcode & omask) != op->opcode) + { + as_bad (_("mask trims opcode bits for %s"), + op->name); + bad_insn = TRUE; + } + + /* The operands must not overlap the opcode or each other. */ + for (o = op->operands; *o; ++o) + if (*o >= num_powerpc_operands) + { + as_bad (_("operand index error for %s"), + op->name); + bad_insn = TRUE; + } + else + { + const struct powerpc_operand *operand = &powerpc_operands[*o]; + if (operand->shift >= 0) + { + unsigned long mask = operand->bitm << operand->shift; + if (omask & mask) + { + as_bad (_("operand %d overlap in %s"), + (int) (o - op->operands), op->name); + bad_insn = TRUE; + } + omask |= mask; + } + } + } if ((op->flags & ppc_cpu & ~(PPC_OPCODE_32 | PPC_OPCODE_64)) != 0 && ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == 0 || ((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)))) + && !(ppc_cpu & op->deprecated)) { const char *retval; - retval = hash_insert (ppc_hash, op->name, (PTR) op); + retval = hash_insert (ppc_hash, op->name, (void *) op); if (retval != NULL) { /* Ignore Power duplicates for -m601. */ @@ -1281,16 +1490,16 @@ ppc_setup_opcodes (void) && (op->flags & PPC_OPCODE_POWER) != 0) continue; - as_bad (_("Internal assembler error for instruction %s"), + as_bad (_("duplicate instruction %s"), op->name); - dup_insn = TRUE; + bad_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); + hash_insert (ppc_hash, op->name, (void *) op); /* Insert the macros into a hash table. */ ppc_macro_hash = hash_new (); @@ -1302,16 +1511,16 @@ ppc_setup_opcodes (void) { const char *retval; - retval = hash_insert (ppc_macro_hash, macro->name, (PTR) macro); + retval = hash_insert (ppc_macro_hash, macro->name, (void *) macro); if (retval != (const char *) NULL) { - as_bad (_("Internal assembler error for macro %s"), macro->name); - dup_insn = TRUE; + as_bad (_("duplicate macro %s"), macro->name); + bad_insn = TRUE; } } } - if (dup_insn) + if (bad_insn) abort (); } @@ -1320,7 +1529,7 @@ ppc_setup_opcodes (void) opened. */ void -md_begin () +md_begin (void) { ppc_set_cpu (); @@ -1363,7 +1572,7 @@ md_begin () } void -ppc_cleanup () +ppc_cleanup (void) { #ifdef OBJ_ELF if (ppc_apuinfo_list == NULL) @@ -1425,54 +1634,61 @@ ppc_cleanup () /* Insert an operand value into an instruction. */ static unsigned long -ppc_insert_operand (insn, operand, val, file, line) - unsigned long insn; - const struct powerpc_operand *operand; - offsetT val; - char *file; - unsigned int line; +ppc_insert_operand (unsigned long insn, + const struct powerpc_operand *operand, + offsetT val, + ppc_cpu_t cpu, + char *file, + unsigned int line) { - if (operand->bits != 32) + long min, max, right; + + max = operand->bitm; + right = max & -max; + min = 0; + + if ((operand->flags & PPC_OPERAND_SIGNED) != 0) { - long min, max; - offsetT test; + if ((operand->flags & PPC_OPERAND_SIGNOPT) == 0) + max = (max >> 1) & -right; + min = ~max & -right; + } - if ((operand->flags & PPC_OPERAND_SIGNED) != 0) - { - if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0) - max = (1 << operand->bits) - 1; - else - max = (1 << (operand->bits - 1)) - 1; - min = - (1 << (operand->bits - 1)); + if ((operand->flags & PPC_OPERAND_PLUS1) != 0) + max++; - if (!ppc_obj64) - { - /* Some people write 32 bit hex constants with the sign - extension done by hand. This shouldn't really be - valid, but, to permit this code to assemble on a 64 - bit host, we sign extend the 32 bit value. */ - if (val > 0 - && (val & (offsetT) 0x80000000) != 0 - && (val & (offsetT) 0xffffffff) == val) - { - val -= 0x80000000; - val -= 0x80000000; - } - } - } - else - { - max = (1 << operand->bits) - 1; - min = 0; - } + if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0) + { + long tmp = min; + min = -max; + max = -tmp; + } - if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0) - test = - val; - else - test = val; + if (min <= max) + { + /* Some people write constants with the sign extension done by + hand but only up to 32 bits. This shouldn't really be valid, + but, to permit this code to assemble on a 64-bit host, we + sign extend the 32-bit value to 64 bits if so doing makes the + value valid. */ + if (val > max + && (offsetT) (val - 0x80000000 - 0x80000000) >= min + && (offsetT) (val - 0x80000000 - 0x80000000) <= max + && ((val - 0x80000000 - 0x80000000) & (right - 1)) == 0) + val = val - 0x80000000 - 0x80000000; + + /* Similarly, people write expressions like ~(1<<15), and expect + this to be OK for a 32-bit unsigned value. */ + else if (val < min + && (offsetT) (val + 0x80000000 + 0x80000000) >= min + && (offsetT) (val + 0x80000000 + 0x80000000) <= max + && ((val + 0x80000000 + 0x80000000) & (right - 1)) == 0) + val = val + 0x80000000 + 0x80000000; - if (test < (offsetT) min || test > (offsetT) max) - as_bad_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line); + else if (val < min + || val > max + || (val & (right - 1)) != 0) + as_bad_value_out_of_range (_("operand"), val, min, max, file, line); } if (operand->insert) @@ -1480,13 +1696,12 @@ ppc_insert_operand (insn, operand, val, file, line) const char *errmsg; errmsg = NULL; - insn = (*operand->insert) (insn, (long) val, ppc_cpu, &errmsg); + insn = (*operand->insert) (insn, (long) val, cpu, &errmsg); if (errmsg != (const char *) NULL) - as_bad_where (file, line, errmsg); + as_bad_where (file, line, "%s", errmsg); } else - insn |= (((long) val & ((1 << operand->bits) - 1)) - << operand->shift); + insn |= ((long) val & operand->bitm) << operand->shift; return insn; } @@ -1495,9 +1710,7 @@ ppc_insert_operand (insn, operand, val, file, line) #ifdef OBJ_ELF /* Parse @got, etc. and return the desired relocation. */ static bfd_reloc_code_real_type -ppc_elf_suffix (str_p, exp_p) - char **str_p; - expressionS *exp_p; +ppc_elf_suffix (char **str_p, expressionS *exp_p) { struct map_bfd { char *string; @@ -1630,13 +1843,38 @@ ppc_elf_suffix (str_p, exp_p) { 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 == '+') @@ -1675,8 +1913,7 @@ ppc_elf_suffix (str_p, exp_p) /* Like normal .long/.short/.word, except support @got, etc. Clobbers input_line_pointer, checks end-of-line. */ static void -ppc_elf_cons (nbytes) - register int nbytes; /* 1=.byte, 2=.word, 4=.long, 8=.llong. */ +ppc_elf_cons (int nbytes /* 1=.byte, 2=.word, 4=.long, 8=.llong */) { expressionS exp; bfd_reloc_code_real_type reloc; @@ -1712,6 +1949,7 @@ ppc_elf_cons (nbytes) int offset; p = frag_more (nbytes); + memset (p, 0, nbytes); offset = 0; if (target_big_endian) offset = nbytes - size; @@ -1731,8 +1969,7 @@ ppc_elf_cons (nbytes) /* Solaris pseduo op to change to the .rodata section. */ static void -ppc_elf_rdata (xxx) - int xxx; +ppc_elf_rdata (int xxx) { char *save_line = input_line_pointer; static char section[] = ".rodata\n"; @@ -1746,14 +1983,13 @@ ppc_elf_rdata (xxx) /* Pseudo op to make file scope bss items. */ static void -ppc_elf_lcomm (xxx) - int xxx ATTRIBUTE_UNUSED; +ppc_elf_lcomm (int xxx ATTRIBUTE_UNUSED) { - register char *name; - register char c; - register char *p; + char *name; + char c; + char *p; offsetT size; - register symbolS *symbolP; + symbolS *symbolP; offsetT align; segT old_sec; int old_subsec; @@ -1856,9 +2092,7 @@ ppc_elf_lcomm (xxx) fixups for word relocations in writable segments, so we can adjust them at runtime. */ static void -ppc_elf_validate_fix (fixp, seg) - fixS *fixp; - segT seg; +ppc_elf_validate_fix (fixS *fixp, segT seg) { if (fixp->fx_done || fixp->fx_pcrel) return; @@ -1903,7 +2137,7 @@ ppc_elf_validate_fix (fixp, seg) function descriptor sym if the corresponding code sym is used. */ void -ppc_frob_file_before_adjust () +ppc_frob_file_before_adjust (void) { symbolS *symp; asection *toc; @@ -1930,7 +2164,7 @@ ppc_frob_file_before_adjust () dotname = xmalloc (len + 1); dotname[0] = '.'; memcpy (dotname + 1, name, len); - dotsym = symbol_find (dotname); + dotsym = symbol_find_noref (dotname, 1); free (dotname); if (dotsym != NULL && (symbol_used_p (dotsym) || symbol_used_in_reloc_p (dotsym))) @@ -1940,6 +2174,7 @@ ppc_frob_file_before_adjust () toc = bfd_get_section_by_name (stdoutput, ".toc"); if (toc != NULL + && toc_reloc_types != has_large_toc_reloc && bfd_section_size (stdoutput, toc) > 0x10000) as_warn (_("TOC section size exceeds 64k")); @@ -1986,8 +2221,7 @@ enum toc_size_qualifier }; static int -parse_toc_entry (toc_kind) - enum toc_size_qualifier *toc_kind; +parse_toc_entry (enum toc_size_qualifier *toc_kind) { char *start; char *toc_spec; @@ -2051,8 +2285,7 @@ parse_toc_entry (toc_kind) #ifdef OBJ_ELF #define APUID(a,v) ((((a) & 0xffff) << 16) | ((v) & 0xffff)) static void -ppc_apuinfo_section_add (apu, version) - unsigned int apu, version; +ppc_apuinfo_section_add (unsigned int apu, unsigned int version) { unsigned int i; @@ -2098,8 +2331,7 @@ struct ppc_fixup /* This routine is called for each instruction to be assembled. */ void -md_assemble (str) - char *str; +md_assemble (char *str) { char *s; const struct powerpc_opcode *opcode; @@ -2164,7 +2396,6 @@ md_assemble (str) { 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. */ @@ -2224,7 +2455,7 @@ md_assemble (str) { insn = (*operand->insert) (insn, 0L, ppc_cpu, &errmsg); if (errmsg != (const char *) NULL) - as_bad (errmsg); + as_bad ("%s", errmsg); continue; } @@ -2237,7 +2468,7 @@ md_assemble (str) { 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; @@ -2312,7 +2543,7 @@ md_assemble (str) explain. */ if (ex.X_op == O_symbol) { - assert (ex.X_add_symbol != NULL); + gas_assert (ex.X_add_symbol != NULL); if (symbol_get_bfdsym (ex.X_add_symbol)->section != tocdata_section) { @@ -2363,12 +2594,19 @@ md_assemble (str) else #endif /* TE_PE */ { - if (! register_name (&ex)) + if ((reg_names_p && (operand->flags & PPC_OPERAND_CR) != 0) + || !register_name (&ex)) { + char save_lex = lex_type['%']; + if ((operand->flags & PPC_OPERAND_CR) != 0) - cr_operand = TRUE; + { + cr_operand = TRUE; + lex_type['%'] |= LEX_BEGIN_NAME; + } expression (&ex); cr_operand = FALSE; + lex_type['%'] = save_lex; } } @@ -2382,7 +2620,7 @@ md_assemble (str) else if (ex.X_op == O_register) { insn = ppc_insert_operand (insn, operand, ex.X_add_number, - (char *) NULL, 0); + ppc_cpu, (char *) NULL, 0); } else if (ex.X_op == O_constant) { @@ -2451,124 +2689,192 @@ md_assemble (str) } #endif /* OBJ_ELF */ insn = ppc_insert_operand (insn, operand, ex.X_add_number, - (char *) NULL, 0); + ppc_cpu, (char *) NULL, 0); } #ifdef OBJ_ELF - else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED) + else { - /* Some TLS tweaks. */ - switch (reloc) + if (ex.X_op == O_symbol && str[0] == '(') { - default: - break; - case BFD_RELOC_PPC_TLS: - insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2, - (char *) NULL, 0); - break; - /* We'll only use the 32 (or 64) bit form of these relocations - in constants. Instructions get the 16 bit form. */ - case BFD_RELOC_PPC_DTPREL: - reloc = BFD_RELOC_PPC_DTPREL16; - break; - case BFD_RELOC_PPC_TPREL: - reloc = BFD_RELOC_PPC_TPREL16; - break; + const char *sym_name = S_GET_NAME (ex.X_add_symbol); + if (sym_name[0] == '.') + ++sym_name; + + if (strcasecmp (sym_name, "__tls_get_addr") == 0) + { + 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; + } } - /* For the absolute forms of branches, convert the PC - relative form back into the absolute. */ - if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) + if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED) { + /* Some TLS tweaks. */ switch (reloc) { - case BFD_RELOC_PPC_B26: - reloc = BFD_RELOC_PPC_BA26; + default: break; - case BFD_RELOC_PPC_B16: - reloc = BFD_RELOC_PPC_BA16; + + case BFD_RELOC_PPC_TLS: + if (!_bfd_elf_ppc_at_tls_transform (opcode->opcode, 0)) + as_bad (_("@tls may not be used with \"%s\" operands"), + opcode->name); + else if (operand->shift != 11) + as_bad (_("@tls may only be used in last operand")); + else + insn = ppc_insert_operand (insn, operand, + ppc_obj64 ? 13 : 2, + ppc_cpu, (char *) NULL, 0); break; - case BFD_RELOC_PPC_B16_BRTAKEN: - reloc = BFD_RELOC_PPC_BA16_BRTAKEN; + + /* 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_B16_BRNTAKEN: - reloc = BFD_RELOC_PPC_BA16_BRNTAKEN; - break; - default: + case BFD_RELOC_PPC_TPREL: + reloc = BFD_RELOC_PPC_TPREL16; break; } - } - if (ppc_obj64 - && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0) - { + /* 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; + } + } + 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; + toc_reloc_types |= has_small_toc_reloc; 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: + case BFD_RELOC_PPC64_TOC16_HI: + case BFD_RELOC_PPC64_TOC16_HA: + toc_reloc_types |= has_large_toc_reloc; break; default: - as_bad (_("unsupported relocation for DS offset field")); 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. */ @@ -2579,11 +2885,20 @@ md_assemble (str) fixups[fc].reloc = BFD_RELOC_UNUSED; ++fc; } +#endif /* OBJ_ELF */ if (need_paren) { endc = ')'; need_paren = 0; + /* If expecting more operands, then we want to see "),". */ + if (*str == endc && opindex_ptr[1] != 0) + { + do + ++str; + while (ISSPACE (*str)); + endc = ','; + } } else if ((operand->flags & PPC_OPERAND_PARENS) != 0) { @@ -2614,10 +2929,7 @@ md_assemble (str) #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_E500 | PPC_OPCODE_E500MC)) != 0) { /* These are all version "1". */ if (opcode->flags & PPC_OPCODE_SPE) @@ -2658,9 +2970,6 @@ md_assemble (str) 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; @@ -2707,13 +3016,18 @@ md_assemble (str) } } 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))); + } } } @@ -2723,16 +3037,14 @@ md_assemble (str) around operands here. */ static void -ppc_macro (str, macro) - char *str; - const struct powerpc_macro *macro; +ppc_macro (char *str, const struct powerpc_macro *macro) { char *operands[10]; unsigned int count; char *s; unsigned int len; const char *format; - int arg; + unsigned int arg; char *send; char *complete; @@ -2770,7 +3082,7 @@ ppc_macro (str, macro) else { arg = strtol (format + 1, &send, 10); - know (send != format && arg >= 0 && arg < count); + know (send != format && arg < count); len += strlen (operands[arg]); format = send; } @@ -2798,35 +3110,10 @@ ppc_macro (str, macro) } #ifdef OBJ_ELF -/* For ELF, add support for SHF_EXCLUDE and SHT_ORDERED. */ - -int -ppc_section_letter (letter, ptr_msg) - int letter; - char **ptr_msg; -{ - if (letter == 'e') - return SHF_EXCLUDE; - - *ptr_msg = _("Bad .section directive: want a,e,w,x,M,S,G,T in string"); - return -1; -} +/* For ELF, add support for SHT_ORDERED. */ int -ppc_section_word (str, len) - char *str; - size_t len; -{ - if (len == 7 && strncmp (str, "exclude", 7) == 0) - return SHF_EXCLUDE; - - return -1; -} - -int -ppc_section_type (str, len) - char *str; - size_t len; +ppc_section_type (char *str, size_t len) { if (len == 7 && strncmp (str, "ordered", 7) == 0) return SHT_ORDERED; @@ -2835,17 +3122,11 @@ ppc_section_type (str, len) } int -ppc_section_flags (flags, attr, type) - int flags; - int attr; - int type; +ppc_section_flags (flagword flags, bfd_vma attr ATTRIBUTE_UNUSED, int type) { if (type == SHT_ORDERED) flags |= SEC_ALLOC | SEC_LOAD | SEC_SORT_ENTRIES; - if (attr & SHF_EXCLUDE) - flags |= SEC_EXCLUDE; - return flags; } #endif /* OBJ_ELF */ @@ -2857,8 +3138,7 @@ ppc_section_flags (flags, attr, type) pseudo-op, but it can also take a single ASCII string. */ static void -ppc_byte (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_byte (int ignore ATTRIBUTE_UNUSED) { if (*input_line_pointer != '\"') { @@ -2902,8 +3182,7 @@ static bfd_boolean ppc_stab_symbol; aligns .comm and .lcomm to 4 bytes. */ static void -ppc_comm (lcomm) - int lcomm; +ppc_comm (int lcomm) { asection *current_seg = now_seg; subsegT current_subseg = now_subseg; @@ -3057,8 +3336,7 @@ ppc_comm (lcomm) optional second argument is the alignment (the default is 2). */ static void -ppc_csect (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_csect (int ignore ATTRIBUTE_UNUSED) { char *name; char endc; @@ -3075,7 +3353,7 @@ ppc_csect (ignore) if (S_GET_NAME (sym)[0] == '\0') { /* An unnamed csect is assumed to be [PR]. */ - symbol_get_tc (sym)->class = XMC_PR; + symbol_get_tc (sym)->symbol_class = XMC_PR; } align = 2; @@ -3093,9 +3371,7 @@ ppc_csect (ignore) /* Change to a different csect. */ static void -ppc_change_csect (sym, align) - symbolS *sym; - offsetT align; +ppc_change_csect (symbolS *sym, offsetT align) { if (S_IS_DEFINED (sym)) subseg_set (S_GET_SEGMENT (sym), symbol_get_tc (sym)->subseg); @@ -3113,7 +3389,7 @@ ppc_change_csect (sym, align) data section. */ after_toc = 0; is_code = 0; - switch (symbol_get_tc (sym)->class) + switch (symbol_get_tc (sym)->symbol_class) { case XMC_PR: case XMC_RO: @@ -3195,8 +3471,7 @@ ppc_change_csect (sym, align) convenience of people who aren't used to XCOFF. */ static void -ppc_section (type) - int type; +ppc_section (int type) { const char *name; symbolS *sym; @@ -3220,8 +3495,7 @@ ppc_section (type) we do permit the user to name the text or data section. */ static void -ppc_named_section (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_named_section (int ignore ATTRIBUTE_UNUSED) { char *user_name; const char *real_name; @@ -3255,8 +3529,7 @@ ppc_named_section (ignore) /* The .extern pseudo-op. We create an undefined symbol. */ static void -ppc_extern (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_extern (int ignore ATTRIBUTE_UNUSED) { char *name; char endc; @@ -3274,8 +3547,7 @@ ppc_extern (ignore) /* The .lglobl pseudo-op. Keep the symbol in the symbol table. */ static void -ppc_lglobl (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_lglobl (int ignore ATTRIBUTE_UNUSED) { char *name; char endc; @@ -3293,12 +3565,63 @@ ppc_lglobl (ignore) demand_empty_rest_of_line (); } +/* The .ref pseudo-op. It takes a list of symbol names and inserts R_REF + relocations at the beginning of the current csect. + + (In principle, there's no reason why the relocations _have_ to be at + the beginning. Anywhere in the csect would do. However, inserting + at the beginning is what the native assmebler does, and it helps to + deal with cases where the .ref statements follow the section contents.) + + ??? .refs don't work for empty .csects. However, the native assembler + doesn't report an error in this case, and neither yet do we. */ + +static void +ppc_ref (int ignore ATTRIBUTE_UNUSED) +{ + char *name; + char c; + + if (ppc_current_csect == NULL) + { + as_bad (_(".ref outside .csect")); + ignore_rest_of_line (); + return; + } + + do + { + name = input_line_pointer; + c = get_symbol_end (); + + fix_at_start (symbol_get_frag (ppc_current_csect), 0, + symbol_find_or_make (name), 0, FALSE, BFD_RELOC_NONE); + + *input_line_pointer = c; + SKIP_WHITESPACE (); + c = *input_line_pointer; + if (c == ',') + { + input_line_pointer++; + SKIP_WHITESPACE (); + if (is_end_of_line[(unsigned char) *input_line_pointer]) + { + as_bad (_("missing symbol name")); + ignore_rest_of_line (); + return; + } + } + } + while (c == ','); + + demand_empty_rest_of_line (); +} + /* The .rename pseudo-op. The RS/6000 assembler can rename symbols, although I don't know why it bothers. */ static void -ppc_rename (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_rename (int ignore ATTRIBUTE_UNUSED) { char *name; char endc; @@ -3333,8 +3656,7 @@ ppc_rename (ignore) always zero, and I am assuming it is the type. */ static void -ppc_stabx (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_stabx (int ignore ATTRIBUTE_UNUSED) { char *name; int len; @@ -3460,8 +3782,7 @@ ppc_stabx (ignore) gets an aux entry like that used for a csect. */ static void -ppc_function (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_function (int ignore ATTRIBUTE_UNUSED) { char *name; char endc; @@ -3510,22 +3831,22 @@ ppc_function (ignore) symbol_set_value_expression (ext_sym, &exp); } - if (symbol_get_tc (ext_sym)->class == -1) - symbol_get_tc (ext_sym)->class = XMC_PR; + if (symbol_get_tc (ext_sym)->symbol_class == -1) + symbol_get_tc (ext_sym)->symbol_class = XMC_PR; symbol_get_tc (ext_sym)->output = 1; if (*input_line_pointer == ',') { - expressionS ignore; + expressionS exp; /* Ignore the third argument. */ ++input_line_pointer; - expression (&ignore); + expression (& exp); if (*input_line_pointer == ',') { /* Ignore the fourth argument. */ ++input_line_pointer; - expression (&ignore); + expression (& exp); if (*input_line_pointer == ',') { /* The fifth argument is the function size. */ @@ -3554,8 +3875,7 @@ ppc_function (ignore) static symbolS *saved_bi_sym = 0; static void -ppc_bf (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_bf (int ignore ATTRIBUTE_UNUSED) { symbolS *sym; @@ -3590,8 +3910,7 @@ ppc_bf (ignore) most recent ".bf" symbol. */ static void -ppc_ef (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_ef (int ignore ATTRIBUTE_UNUSED) { symbolS *sym; @@ -3615,8 +3934,7 @@ ppc_ef (ignore) is encountered. */ static void -ppc_biei (ei) - int ei; +ppc_biei (int ei) { static symbolS *last_biei; @@ -3670,8 +3988,7 @@ ppc_biei (ei) .bs symbol is the index of this csect symbol. */ static void -ppc_bs (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_bs (int ignore ATTRIBUTE_UNUSED) { char *name; char endc; @@ -3706,8 +4023,7 @@ ppc_bs (ignore) /* The .es pseudo-op. Generate a C_ESTART symbol named .es. */ static void -ppc_es (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_es (int ignore ATTRIBUTE_UNUSED) { symbolS *sym; @@ -3731,8 +4047,7 @@ ppc_es (ignore) line number. */ static void -ppc_bb (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_bb (int ignore ATTRIBUTE_UNUSED) { symbolS *sym; @@ -3758,8 +4073,7 @@ ppc_bb (ignore) line number. */ static void -ppc_eb (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_eb (int ignore ATTRIBUTE_UNUSED) { symbolS *sym; @@ -3783,8 +4097,7 @@ ppc_eb (ignore) specified name. */ static void -ppc_bc (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_bc (int ignore ATTRIBUTE_UNUSED) { char *name; int len; @@ -3806,8 +4119,7 @@ ppc_bc (ignore) /* The .ec pseudo-op. This just creates a C_ECOMM symbol. */ static void -ppc_ec (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_ec (int ignore ATTRIBUTE_UNUSED) { symbolS *sym; @@ -3826,8 +4138,7 @@ ppc_ec (ignore) /* The .toc pseudo-op. Switch to the .toc subsegment. */ static void -ppc_toc (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_toc (int ignore ATTRIBUTE_UNUSED) { if (ppc_toc_csect != (symbolS *) NULL) subseg_set (data_section, symbol_get_tc (ppc_toc_csect)->subseg); @@ -3873,8 +4184,7 @@ ppc_toc (ignore) .short pseudo-op, and we want to be compatible. */ static void -ppc_xcoff_cons (log_size) - int log_size; +ppc_xcoff_cons (int log_size) { frag_align (log_size, 0, 0); record_alignment (now_seg, log_size); @@ -3882,8 +4192,7 @@ ppc_xcoff_cons (log_size) } static void -ppc_vbyte (dummy) - int dummy ATTRIBUTE_UNUSED; +ppc_vbyte (int dummy ATTRIBUTE_UNUSED) { expressionS exp; int byte_count; @@ -3926,8 +4235,7 @@ ppc_vbyte (dummy) the first argument is simply ignored. */ static void -ppc_tc (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_tc (int ignore ATTRIBUTE_UNUSED) { #ifdef OBJ_XCOFF @@ -3957,7 +4265,7 @@ ppc_tc (ignore) symbolS *label; label = symbol_get_tc (ppc_current_csect)->within; - if (symbol_get_tc (label)->class != XMC_TC0) + if (symbol_get_tc (label)->symbol_class != XMC_TC0) { as_bad (_(".tc with no label")); ignore_rest_of_line (); @@ -3977,7 +4285,7 @@ ppc_tc (ignore) S_SET_SEGMENT (sym, now_seg); symbol_set_frag (sym, frag_now); S_SET_VALUE (sym, (valueT) frag_now_fix ()); - symbol_get_tc (sym)->class = XMC_TC; + symbol_get_tc (sym)->symbol_class = XMC_TC; symbol_get_tc (sym)->output = 1; ppc_frob_label (sym); @@ -3989,6 +4297,7 @@ ppc_tc (ignore) /* Skip the TOC symbol name. */ while (is_part_of_name (*input_line_pointer) + || *input_line_pointer == ' ' || *input_line_pointer == '[' || *input_line_pointer == ']' || *input_line_pointer == '{' @@ -4013,12 +4322,11 @@ ppc_tc (ignore) /* Pseudo-op .machine. */ static void -ppc_machine (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_machine (int ignore ATTRIBUTE_UNUSED) { char *cpu_string; #define MAX_HISTORY 100 - static unsigned long *cpu_history; + static ppc_cpu_t *cpu_history; static int curr_hist; SKIP_WHITESPACE (); @@ -4039,7 +4347,8 @@ ppc_machine (ignore) if (cpu_string != NULL) { - unsigned long old_cpu = ppc_cpu; + ppc_cpu_t old_cpu = ppc_cpu; + ppc_cpu_t new_cpu; char *p; for (p = cpu_string; *p != 0; p++) @@ -4062,8 +4371,8 @@ ppc_machine (ignore) else ppc_cpu = cpu_history[--curr_hist]; } - else if (parse_cpu (cpu_string)) - ; + else if ((new_cpu = ppc_parse_cpu (ppc_cpu, cpu_string)) != 0) + ppc_cpu = new_cpu; else as_bad (_("invalid machine `%s'"), cpu_string); @@ -4077,11 +4386,10 @@ ppc_machine (ignore) /* See whether a symbol is in the TOC section. */ static int -ppc_is_toc_sym (sym) - symbolS *sym; +ppc_is_toc_sym (symbolS *sym) { #ifdef OBJ_XCOFF - return symbol_get_tc (sym)->class == XMC_TC; + return symbol_get_tc (sym)->symbol_class == XMC_TC; #endif #ifdef OBJ_ELF const char *sname = segment_name (S_GET_SEGMENT (sym)); @@ -4099,8 +4407,7 @@ ppc_is_toc_sym (sym) /* Set the current section. */ static void -ppc_set_current_section (new) - segT new; +ppc_set_current_section (segT new) { ppc_previous_section = ppc_current_section; ppc_current_section = new; @@ -4112,8 +4419,7 @@ ppc_set_current_section (new) warnings: "No previous section" */ static void -ppc_previous (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_previous (int ignore ATTRIBUTE_UNUSED) { symbolS *tmp; @@ -4144,8 +4450,7 @@ ppc_previous (ignore) handling, debugging, etc. */ static void -ppc_pdata (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_pdata (int ignore ATTRIBUTE_UNUSED) { if (pdata_section == 0) { @@ -4179,8 +4484,7 @@ ppc_pdata (ignore) debugging, etc. */ static void -ppc_ydata (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_ydata (int ignore ATTRIBUTE_UNUSED) { if (ydata_section == 0) { @@ -4216,8 +4520,7 @@ ppc_ydata (ignore) function descriptors, etc. */ static void -ppc_reldata (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_reldata (int ignore ATTRIBUTE_UNUSED) { if (reldata_section == 0) { @@ -4247,8 +4550,7 @@ ppc_reldata (ignore) 3 - double word aligned (that would be 4 byte boundary) */ static void -ppc_rdata (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_rdata (int ignore ATTRIBUTE_UNUSED) { if (rdata_section == 0) { @@ -4274,8 +4576,7 @@ ppc_rdata (ignore) warnings: None */ static void -ppc_ualong (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_ualong (int ignore ATTRIBUTE_UNUSED) { /* Try for long. */ cons (4); @@ -4289,8 +4590,7 @@ ppc_ualong (ignore) warnings: Missing symbol name */ static void -ppc_znop (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_znop (int ignore ATTRIBUTE_UNUSED) { unsigned long insn; const struct powerpc_opcode *opcode; @@ -4342,14 +4642,13 @@ ppc_znop (ignore) warnings: */ static void -ppc_pe_comm (lcomm) - int lcomm; +ppc_pe_comm (int lcomm) { - register char *name; - register char c; - register char *p; + char *name; + char c; + char *p; offsetT temp; - register symbolS *symbolP; + symbolS *symbolP; offsetT align; name = input_line_pointer; @@ -4415,6 +4714,7 @@ ppc_pe_comm (lcomm) { S_SET_VALUE (symbolP, (valueT) temp); S_SET_EXTERNAL (symbolP); + S_SET_SEGMENT (symbolP, bfd_com_section_ptr); } demand_empty_rest_of_line (); @@ -4471,8 +4771,7 @@ ppc_pe_comm (lcomm) */ void -ppc_pe_section (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_pe_section (int ignore ATTRIBUTE_UNUSED) { /* Strip out the section name. */ char *section_name; @@ -4560,7 +4859,7 @@ ppc_pe_section (ignore) case 'R': /* Remove section at link time */ flags |= SEC_NEVER_LOAD; break; - +#if IFLICT_BRAIN_DAMAGE /* Section Protection */ case 'r': /* section is readable */ flags |= IMAGE_SCN_MEM_READ; @@ -4604,7 +4903,7 @@ ppc_pe_section (ignore) flags |= IMAGE_SCN_ALIGN_64BYTES; align = 6; break; - +#endif default: as_bad (_("unknown section attribute '%c'"), *input_line_pointer); @@ -4630,12 +4929,10 @@ ppc_pe_section (ignore) } bfd_set_section_alignment (stdoutput, sec, align); - } static void -ppc_pe_function (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_pe_function (int ignore ATTRIBUTE_UNUSED) { char *name; char endc; @@ -4657,8 +4954,7 @@ ppc_pe_function (ignore) } static void -ppc_pe_tocd (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_pe_tocd (int ignore ATTRIBUTE_UNUSED) { if (tocdata_section == 0) { @@ -4683,8 +4979,7 @@ ppc_pe_tocd (ignore) /* Don't adjust TOC relocs to use the section symbol. */ int -ppc_pe_fix_adjustable (fix) - fixS *fix; +ppc_pe_fix_adjustable (fixS *fix) { return fix->fx_r_type != BFD_RELOC_PPC_TOC16; } @@ -4699,8 +4994,7 @@ ppc_pe_fix_adjustable (fix) any, to use square brackets, and to be in upper case. */ char * -ppc_canonicalize_symbol_name (name) - char *name; +ppc_canonicalize_symbol_name (char *name) { char *s; @@ -4737,8 +5031,7 @@ ppc_canonicalize_symbol_name (name) called whenever a new symbol is created. */ void -ppc_symbol_new_hook (sym) - symbolS *sym; +ppc_symbol_new_hook (symbolS *sym) { struct ppc_tc_sy *tc; const char *s; @@ -4746,7 +5039,7 @@ ppc_symbol_new_hook (sym) tc = symbol_get_tc (sym); tc->next = NULL; tc->output = 0; - tc->class = -1; + tc->symbol_class = -1; tc->real_name = NULL; tc->subseg = 0; tc->align = 0; @@ -4769,55 +5062,55 @@ ppc_symbol_new_hook (sym) { case 'B': if (strcmp (s, "BS]") == 0) - tc->class = XMC_BS; + tc->symbol_class = XMC_BS; break; case 'D': if (strcmp (s, "DB]") == 0) - tc->class = XMC_DB; + tc->symbol_class = XMC_DB; else if (strcmp (s, "DS]") == 0) - tc->class = XMC_DS; + tc->symbol_class = XMC_DS; break; case 'G': if (strcmp (s, "GL]") == 0) - tc->class = XMC_GL; + tc->symbol_class = XMC_GL; break; case 'P': if (strcmp (s, "PR]") == 0) - tc->class = XMC_PR; + tc->symbol_class = XMC_PR; break; case 'R': if (strcmp (s, "RO]") == 0) - tc->class = XMC_RO; + tc->symbol_class = XMC_RO; else if (strcmp (s, "RW]") == 0) - tc->class = XMC_RW; + tc->symbol_class = XMC_RW; break; case 'S': if (strcmp (s, "SV]") == 0) - tc->class = XMC_SV; + tc->symbol_class = XMC_SV; break; case 'T': if (strcmp (s, "TC]") == 0) - tc->class = XMC_TC; + tc->symbol_class = XMC_TC; else if (strcmp (s, "TI]") == 0) - tc->class = XMC_TI; + tc->symbol_class = XMC_TI; else if (strcmp (s, "TB]") == 0) - tc->class = XMC_TB; + tc->symbol_class = XMC_TB; else if (strcmp (s, "TC0]") == 0 || strcmp (s, "T0]") == 0) - tc->class = XMC_TC0; + tc->symbol_class = XMC_TC0; break; case 'U': if (strcmp (s, "UA]") == 0) - tc->class = XMC_UA; + tc->symbol_class = XMC_UA; else if (strcmp (s, "UC]") == 0) - tc->class = XMC_UC; + tc->symbol_class = XMC_UC; break; case 'X': if (strcmp (s, "XO]") == 0) - tc->class = XMC_XO; + tc->symbol_class = XMC_XO; break; } - if (tc->class == -1) + if (tc->symbol_class == -1) as_bad (_("Unrecognized symbol suffix")); } @@ -4826,19 +5119,22 @@ ppc_symbol_new_hook (sym) follows the csect symbol. */ void -ppc_frob_label (sym) - symbolS *sym; +ppc_frob_label (symbolS *sym) { if (ppc_current_csect != (symbolS *) NULL) { - if (symbol_get_tc (sym)->class == -1) - symbol_get_tc (sym)->class = symbol_get_tc (ppc_current_csect)->class; + if (symbol_get_tc (sym)->symbol_class == -1) + symbol_get_tc (sym)->symbol_class = symbol_get_tc (ppc_current_csect)->symbol_class; symbol_remove (sym, &symbol_rootP, &symbol_lastP); symbol_append (sym, symbol_get_tc (ppc_current_csect)->within, &symbol_rootP, &symbol_lastP); symbol_get_tc (ppc_current_csect)->within = sym; } + +#ifdef OBJ_ELF + dwarf2_emit_label (sym); +#endif } /* This variable is set by ppc_frob_symbol if any absolute symbols are @@ -4853,8 +5149,7 @@ static bfd_boolean ppc_saw_abs; symbol table. */ int -ppc_frob_symbol (sym) - symbolS *sym; +ppc_frob_symbol (symbolS *sym) { static symbolS *ppc_last_function; static symbolS *set_end; @@ -4942,6 +5237,7 @@ ppc_frob_symbol (sym) S_SET_STORAGE_CLASS (sym, C_HIDEXT); if (S_GET_STORAGE_CLASS (sym) == C_EXT + || S_GET_STORAGE_CLASS (sym) == C_AIX_WEAKEXT || S_GET_STORAGE_CLASS (sym) == C_HIDEXT) { int i; @@ -4951,7 +5247,7 @@ ppc_frob_symbol (sym) i = S_GET_NUMBER_AUXILIARY (sym); S_SET_NUMBER_AUXILIARY (sym, i + 1); a = &coffsymbol (symbol_get_bfdsym (sym))->native[i + 1].u.auxent; - if (symbol_get_tc (sym)->class == XMC_TC0) + if (symbol_get_tc (sym)->symbol_class == XMC_TC0) { /* This is the TOC table. */ know (strcmp (S_GET_NAME (sym), "TOC") == 0); @@ -4980,9 +5276,9 @@ ppc_frob_symbol (sym) a->x_csect.x_scnlen.l = symbol_get_frag (sym)->fr_offset; a->x_csect.x_smtyp = (symbol_get_tc (sym)->align << 3) | XTY_CM; if (S_IS_EXTERNAL (sym)) - symbol_get_tc (sym)->class = XMC_RW; + symbol_get_tc (sym)->symbol_class = XMC_RW; else - symbol_get_tc (sym)->class = XMC_BS; + symbol_get_tc (sym)->symbol_class = XMC_BS; } else if (S_GET_SEGMENT (sym) == absolute_section) { @@ -4990,8 +5286,8 @@ ppc_frob_symbol (sym) ppc_adjust_symtab. */ ppc_saw_abs = TRUE; a->x_csect.x_smtyp = XTY_LD; - if (symbol_get_tc (sym)->class == -1) - symbol_get_tc (sym)->class = XMC_XO; + if (symbol_get_tc (sym)->symbol_class == -1) + symbol_get_tc (sym)->symbol_class = XMC_XO; } else if (! S_IS_DEFINED (sym)) { @@ -4999,17 +5295,17 @@ ppc_frob_symbol (sym) a->x_csect.x_scnlen.l = 0; a->x_csect.x_smtyp = XTY_ER; } - else if (symbol_get_tc (sym)->class == XMC_TC) + else if (symbol_get_tc (sym)->symbol_class == XMC_TC) { symbolS *next; /* This is a TOC definition. x_scnlen is the size of the TOC entry. */ next = symbol_next (sym); - while (symbol_get_tc (next)->class == XMC_TC0) + while (symbol_get_tc (next)->symbol_class == XMC_TC0) next = symbol_next (next); if (next == (symbolS *) NULL - || symbol_get_tc (next)->class != XMC_TC) + || symbol_get_tc (next)->symbol_class != XMC_TC) { if (ppc_after_toc_frag == (fragS *) NULL) a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput, @@ -5069,10 +5365,10 @@ ppc_frob_symbol (sym) a->x_csect.x_parmhash = 0; a->x_csect.x_snhash = 0; - if (symbol_get_tc (sym)->class == -1) + if (symbol_get_tc (sym)->symbol_class == -1) a->x_csect.x_smclas = XMC_PR; else - a->x_csect.x_smclas = symbol_get_tc (sym)->class; + a->x_csect.x_smclas = symbol_get_tc (sym)->symbol_class; a->x_csect.x_stab = 0; a->x_csect.x_snstab = 0; @@ -5117,7 +5413,7 @@ ppc_frob_symbol (sym) absolute symbols. */ void -ppc_adjust_symtab () +ppc_adjust_symtab (void) { symbolS *sym; @@ -5163,8 +5459,7 @@ ppc_adjust_symtab () turn. */ void -ppc_frob_section (sec) - asection *sec; +ppc_frob_section (asection *sec) { static bfd_vma vma = 0; @@ -5175,71 +5470,17 @@ ppc_frob_section (sec) #endif /* OBJ_XCOFF */ -/* Turn a string in input_line_pointer into a floating point constant - of type TYPE, and store the appropriate bytes in *LITP. The number - of LITTLENUMS emitted is stored in *SIZEP. An error message is - returned, or NULL on OK. */ - char * -md_atof (type, litp, sizep) - int type; - char *litp; - int *sizep; +md_atof (int type, char *litp, int *sizep) { - int prec; - LITTLENUM_TYPE words[4]; - char *t; - int i; - - switch (type) - { - case 'f': - prec = 2; - break; - - case 'd': - prec = 4; - break; - - default: - *sizep = 0; - return _("bad call to md_atof"); - } - - t = atof_ieee (input_line_pointer, type, words); - if (t) - input_line_pointer = t; - - *sizep = prec * 2; - - if (target_big_endian) - { - for (i = 0; i < prec; i++) - { - md_number_to_chars (litp, (valueT) words[i], 2); - litp += 2; - } - } - else - { - for (i = prec - 1; i >= 0; i--) - { - md_number_to_chars (litp, (valueT) words[i], 2); - litp += 2; - } - } - - return NULL; + return ieee_md_atof (type, litp, sizep, target_big_endian); } /* Write a value out to the object file, using the appropriate endianness. */ void -md_number_to_chars (buf, val, n) - char *buf; - valueT val; - int n; +md_number_to_chars (char *buf, valueT val, int n) { if (target_big_endian) number_to_chars_bigendian (buf, val, n); @@ -5250,21 +5491,22 @@ md_number_to_chars (buf, val, n) /* Align a section (I don't know why this is machine dependent). */ valueT -md_section_align (seg, addr) - asection *seg; - valueT addr; +md_section_align (asection *seg ATTRIBUTE_UNUSED, valueT addr) { +#ifdef OBJ_ELF + return addr; +#else int align = bfd_get_section_alignment (stdoutput, seg); return ((addr + (1 << align) - 1) & (-1 << align)); +#endif } /* We don't have any form of relaxing. */ int -md_estimate_size_before_relax (fragp, seg) - fragS *fragp ATTRIBUTE_UNUSED; - asection *seg ATTRIBUTE_UNUSED; +md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED, + asection *seg ATTRIBUTE_UNUSED) { abort (); return 0; @@ -5273,10 +5515,9 @@ md_estimate_size_before_relax (fragp, seg) /* Convert a machine dependent frag. We never generate these. */ void -md_convert_frag (abfd, sec, fragp) - bfd *abfd ATTRIBUTE_UNUSED; - asection *sec ATTRIBUTE_UNUSED; - fragS *fragp ATTRIBUTE_UNUSED; +md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec ATTRIBUTE_UNUSED, + fragS *fragp ATTRIBUTE_UNUSED) { abort (); } @@ -5284,8 +5525,7 @@ md_convert_frag (abfd, sec, fragp) /* We have no need to default values of symbols. */ symbolS * -md_undefined_symbol (name) - char *name ATTRIBUTE_UNUSED; +md_undefined_symbol (char *name ATTRIBUTE_UNUSED) { return 0; } @@ -5296,9 +5536,7 @@ md_undefined_symbol (name) given a PC relative reloc. */ long -md_pcrel_from_section (fixp, sec) - fixS *fixp; - segT sec ATTRIBUTE_UNUSED; +md_pcrel_from_section (fixS *fixp, segT sec ATTRIBUTE_UNUSED) { return fixp->fx_frag->fr_address + fixp->fx_where; } @@ -5311,8 +5549,7 @@ md_pcrel_from_section (fixp, sec) corresponding .tc symbol. */ int -ppc_fix_adjustable (fix) - fixS *fix; +ppc_fix_adjustable (fixS *fix) { valueT val = resolve_symbol_value (fix->fx_addsy); segT symseg = S_GET_SEGMENT (fix->fx_addsy); @@ -5336,9 +5573,9 @@ ppc_fix_adjustable (fix) { TC_SYMFIELD_TYPE *sy_tc = symbol_get_tc (sy); - if (sy_tc->class == XMC_TC0) + if (sy_tc->symbol_class == XMC_TC0) continue; - if (sy_tc->class != XMC_TC) + if (sy_tc->symbol_class != XMC_TC) break; if (val == resolve_symbol_value (sy)) { @@ -5355,8 +5592,8 @@ ppc_fix_adjustable (fix) /* Possibly adjust the reloc to be against the csect. */ tc = symbol_get_tc (fix->fx_addsy); if (tc->subseg == 0 - && tc->class != XMC_TC0 - && tc->class != XMC_TC + && tc->symbol_class != XMC_TC0 + && tc->symbol_class != XMC_TC && symseg != bss_section /* Don't adjust if this is a reloc in the toc section. */ && (symseg != data_section @@ -5437,8 +5674,7 @@ ppc_fix_adjustable (fix) between two csects in the same section. */ int -ppc_force_relocation (fix) - fixS *fix; +ppc_force_relocation (fixS *fix) { /* At this point fix->fx_addsy should already have been converted to a csect symbol. If the csect does not include the fragment, then @@ -5463,8 +5699,7 @@ ppc_force_relocation (fix) will be emitted for a fixup. */ int -ppc_force_relocation (fix) - fixS *fix; +ppc_force_relocation (fixS *fix) { /* Branch prediction relocations must force a relocation, as must the vtable description relocs. */ @@ -5489,8 +5724,7 @@ ppc_force_relocation (fix) } int -ppc_fix_adjustable (fix) - fixS *fix; +ppc_fix_adjustable (fixS *fix) { return (fix->fx_r_type != BFD_RELOC_16_GOTOFF && fix->fx_r_type != BFD_RELOC_LO16_GOTOFF @@ -5504,6 +5738,53 @@ ppc_fix_adjustable (fix) } #endif +/* Implement HANDLE_ALIGN. This writes the NOP pattern into an + rs_align_code frag. */ + +void +ppc_handle_align (struct frag *fragP) +{ + valueT count = (fragP->fr_next->fr_address + - (fragP->fr_address + fragP->fr_fix)); + + if (count != 0 && (count & 3) == 0) + { + char *dest = fragP->fr_literal + fragP->fr_fix; + + fragP->fr_var = 4; + md_number_to_chars (dest, 0x60000000, 4); + + if ((ppc_cpu & PPC_OPCODE_POWER6) != 0 + || (ppc_cpu & PPC_OPCODE_POWER7) != 0) + { + /* For power6 and power7, we want the last nop to be a group + terminating one. Do this by inserting an rs_fill frag immediately + after this one, with its address set to the last nop location. + This will automatically reduce the number of nops in the current + frag by one. */ + if (count > 4) + { + struct frag *group_nop = xmalloc (SIZEOF_STRUCT_FRAG + 4); + + memcpy (group_nop, fragP, SIZEOF_STRUCT_FRAG); + group_nop->fr_address = group_nop->fr_next->fr_address - 4; + group_nop->fr_fix = 0; + group_nop->fr_offset = 1; + group_nop->fr_type = rs_fill; + fragP->fr_next = group_nop; + dest = group_nop->fr_literal; + } + + if ((ppc_cpu & PPC_OPCODE_POWER7) != 0) + /* power7 group terminating nop: "ori 2,2,0". */ + md_number_to_chars (dest, 0x60420000, 4); + else + /* power6 group terminating nop: "ori 1,1,0". */ + md_number_to_chars (dest, 0x60210000, 4); + } + } +} + /* Apply a fixup to the object code. This is called for all the fixups we generated by the call to fix_new_exp, above. In the call above we used a reloc code which was the largest legal reloc code @@ -5514,10 +5795,7 @@ ppc_fix_adjustable (fix) fixup. */ void -md_apply_fix (fixP, valP, seg) - fixS *fixP; - valueT * valP; - segT seg ATTRIBUTE_UNUSED; +md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { valueT value = * valP; @@ -5532,23 +5810,24 @@ md_apply_fix (fixP, valP, seg) fixP->fx_done = 1; #else /* FIXME FIXME FIXME: The value we are passed in *valP includes - the symbol values. Since we are using BFD_ASSEMBLER, if we are - doing this relocation the code in write.c is going to call - bfd_install_relocation, which is also going to use the symbol - value. That means that if the reloc is fully resolved we want to - use *valP since bfd_install_relocation is not being used. - However, if the reloc is not fully resolved we do not want to use - *valP, and must use fx_offset instead. However, if the reloc - is PC relative, we do want to use *valP since it includes the - result of md_pcrel_from. This is confusing. */ + the symbol values. If we are doing this relocation the code in + write.c is going to call bfd_install_relocation, which is also + going to use the symbol value. That means that if the reloc is + fully resolved we want to use *valP since bfd_install_relocation is + not being used. + However, if the reloc is not fully resolved we do not want to + use *valP, and must use fx_offset instead. If the relocation + is PC-relative, we then need to re-apply md_pcrel_from_section + to this new relocation value. */ if (fixP->fx_addsy == (symbolS *) NULL) fixP->fx_done = 1; - else if (fixP->fx_pcrel) - ; - else - value = fixP->fx_offset; + { + value = fixP->fx_offset; + if (fixP->fx_pcrel) + value -= md_pcrel_from_section (fixP, seg); + } #endif if (fixP->fx_subsy != (symbolS *) NULL) @@ -5574,13 +5853,13 @@ md_apply_fix (fixP, valP, seg) csect. Other usages, such as `.long sym', generate relocs. This is the documented behaviour of non-TOC symbols. */ if ((operand->flags & PPC_OPERAND_PARENS) != 0 - && operand->bits == 16 + && (operand->bitm & 0xfff0) == 0xfff0 && operand->shift == 0 && (operand->insert == NULL || ppc_obj64) && fixP->fx_addsy != NULL && symbol_get_tc (fixP->fx_addsy)->subseg != 0 - && symbol_get_tc (fixP->fx_addsy)->class != XMC_TC - && symbol_get_tc (fixP->fx_addsy)->class != XMC_TC0 + && symbol_get_tc (fixP->fx_addsy)->symbol_class != XMC_TC + && symbol_get_tc (fixP->fx_addsy)->symbol_class != XMC_TC0 && S_GET_SEGMENT (fixP->fx_addsy) != bss_section) { value = fixP->fx_offset; @@ -5596,6 +5875,7 @@ md_apply_fix (fixP, valP, seg) else insn = bfd_getl32 ((unsigned char *) where); insn = ppc_insert_operand (insn, operand, (offsetT) value, + fixP->tc_fix_data.ppc_cpu, fixP->fx_file, fixP->fx_line); if (target_big_endian) bfd_putb32 ((bfd_vma) insn, (unsigned char *) where); @@ -5606,17 +5886,17 @@ md_apply_fix (fixP, valP, seg) /* Nothing else to do here. */ return; - assert (fixP->fx_addsy != NULL); + gas_assert (fixP->fx_addsy != NULL); /* Determine a BFD reloc value based on the operand information. We are only prepared to turn a few of the operands into relocs. */ if ((operand->flags & PPC_OPERAND_RELATIVE) != 0 - && operand->bits == 26 + && operand->bitm == 0x3fffffc && operand->shift == 0) fixP->fx_r_type = BFD_RELOC_PPC_B26; else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0 - && operand->bits == 16 + && operand->bitm == 0xfffc && operand->shift == 0) { fixP->fx_r_type = BFD_RELOC_PPC_B16; @@ -5627,11 +5907,11 @@ md_apply_fix (fixP, valP, seg) #endif } else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0 - && operand->bits == 26 + && operand->bitm == 0x3fffffc && operand->shift == 0) fixP->fx_r_type = BFD_RELOC_PPC_BA26; else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0 - && operand->bits == 16 + && operand->bitm == 0xfffc && operand->shift == 0) { fixP->fx_r_type = BFD_RELOC_PPC_BA16; @@ -5643,7 +5923,7 @@ md_apply_fix (fixP, valP, seg) } #if defined (OBJ_XCOFF) || defined (OBJ_ELF) else if ((operand->flags & PPC_OPERAND_PARENS) != 0 - && operand->bits == 16 + && (operand->bitm & 0xfff0) == 0xfff0 && operand->shift == 0) { if (ppc_is_toc_sym (fixP->fx_addsy)) @@ -5810,6 +6090,11 @@ md_apply_fix (fixP, valP, seg) PPC_HA (value), 2); break; +#ifdef OBJ_XCOFF + case BFD_RELOC_NONE: + break; +#endif + #ifdef OBJ_ELF case BFD_RELOC_PPC64_HIGHER: if (fixP->fx_pcrel) @@ -5880,6 +6165,8 @@ md_apply_fix (fixP, valP, seg) break; case BFD_RELOC_PPC_TLS: + case BFD_RELOC_PPC_TLSGD: + case BFD_RELOC_PPC_TLSLD: break; case BFD_RELOC_PPC_DTPMOD: @@ -6029,10 +6316,11 @@ md_apply_fix (fixP, valP, seg) #ifdef TE_PE fixP->fx_addnumber = 0; #else - /* We want to use the offset within the data segment of the - symbol, not the actual VMA of the symbol. */ + /* We want to use the offset within the toc, not the actual VMA + of the symbol. */ fixP->fx_addnumber = - - bfd_get_section_vma (stdoutput, S_GET_SEGMENT (fixP->fx_addsy)); + - bfd_get_section_vma (stdoutput, S_GET_SEGMENT (fixP->fx_addsy)) + - S_GET_VALUE (ppc_toc_csect); #endif } #endif @@ -6041,9 +6329,7 @@ md_apply_fix (fixP, valP, seg) /* Generate a reloc for a fixup. */ arelent * -tc_gen_reloc (seg, fixp) - asection *seg ATTRIBUTE_UNUSED; - fixS *fixp; +tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) { arelent *reloc; @@ -6066,13 +6352,13 @@ tc_gen_reloc (seg, fixp) } void -ppc_cfi_frame_initial_instructions () +ppc_cfi_frame_initial_instructions (void) { cfi_add_CFA_def_cfa (1, 0); } int -tc_ppc_regname_to_dw2regnum (const char *regname) +tc_ppc_regname_to_dw2regnum (char *regname) { unsigned int regnum = -1; unsigned int i;