diff options
Diffstat (limited to 'contrib/binutils/gas/config/tc-ppc.c')
-rw-r--r-- | contrib/binutils/gas/config/tc-ppc.c | 658 |
1 files changed, 339 insertions, 319 deletions
diff --git a/contrib/binutils/gas/config/tc-ppc.c b/contrib/binutils/gas/config/tc-ppc.c index d5bdb9e..a86a3be 100644 --- a/contrib/binutils/gas/config/tc-ppc.c +++ b/contrib/binutils/gas/config/tc-ppc.c @@ -1,6 +1,6 @@ /* 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 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. This file is part of GAS, the GNU Assembler. @@ -20,7 +20,6 @@ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -#include <stdio.h> #include "as.h" #include "safe-ctype.h" #include "subsegs.h" @@ -85,67 +84,57 @@ 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_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,11 +172,9 @@ 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. - Also, anything that can start an operand needs to be mentioned here, +/* Anything that can start an operand needs to be mentioned here, to stop the input scrubber eating whitespace. */ -const char ppc_symbol_chars[] = "+-%["; +const char ppc_symbol_chars[] = "%["; /* The dwarf2 data alignment, adjusted for 32 or 64 bit. */ int ppc_cie_data_alignment; @@ -567,14 +554,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; @@ -611,8 +592,7 @@ reg_name_search (regs, regcount, name) */ static bfd_boolean -register_name (expressionP) - expressionS *expressionP; +register_name (expressionS *expressionP) { int reg_number; char *name; @@ -679,9 +659,7 @@ 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 *expr) { int val; @@ -917,6 +895,18 @@ parse_cpu (const char *arg) | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5); } + else if (strcmp (arg, "power6") == 0) + { + ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC + | PPC_OPCODE_64 | PPC_OPCODE_POWER4 + | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6); + } + else if (strcmp (arg, "cell") == 0) + { + ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC + | PPC_OPCODE_64 | PPC_OPCODE_POWER4 + | PPC_OPCODE_CELL); + } /* -mcom means assemble for the common intersection between Power and PowerPC. At present, we just allow the union, rather than the intersection. */ @@ -932,9 +922,7 @@ parse_cpu (const char *arg) } int -md_parse_option (c, arg) - int c; - char *arg; +md_parse_option (int c, char *arg) { switch (c) { @@ -1088,8 +1076,7 @@ md_parse_option (c, arg) } void -md_show_usage (stream) - FILE *stream; +md_show_usage (FILE *stream) { fprintf (stream, _("\ PowerPC options:\n\ @@ -1112,6 +1099,8 @@ PowerPC options:\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\ +-mpower6 generate code for Power6 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, _("\ @@ -1140,7 +1129,7 @@ PowerPC options:\n\ /* 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; @@ -1168,7 +1157,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 (); @@ -1190,7 +1179,7 @@ ppc_arch () } unsigned long -ppc_mach () +ppc_mach (void) { if (ppc_obj64) return bfd_mach_ppc64; @@ -1201,7 +1190,7 @@ ppc_mach () } extern char* -ppc_target_format () +ppc_target_format (void) { #ifdef OBJ_COFF #ifdef TE_PE @@ -1233,11 +1222,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); @@ -1247,10 +1236,77 @@ 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; + + /* 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 @@ -1270,11 +1326,14 @@ ppc_setup_opcodes (void) == (ppc_cpu & PPC_OPCODE_POWER4))) && ((op->flags & PPC_OPCODE_POWER5) == 0 || ((op->flags & PPC_OPCODE_POWER5) - == (ppc_cpu & PPC_OPCODE_POWER5)))) + == (ppc_cpu & PPC_OPCODE_POWER5))) + && ((op->flags & PPC_OPCODE_POWER6) == 0 + || ((op->flags & PPC_OPCODE_POWER6) + == (ppc_cpu & PPC_OPCODE_POWER6)))) { 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. */ @@ -1282,16 +1341,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 (); @@ -1303,16 +1362,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 (); } @@ -1321,7 +1380,7 @@ ppc_setup_opcodes (void) opened. */ void -md_begin () +md_begin (void) { ppc_set_cpu (); @@ -1364,7 +1423,7 @@ md_begin () } void -ppc_cleanup () +ppc_cleanup (void) { #ifdef OBJ_ELF if (ppc_apuinfo_list == NULL) @@ -1426,54 +1485,60 @@ 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, + 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; - if (test < (offsetT) min || test > (offsetT) max) - as_bad_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line); + /* 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; + + 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) @@ -1486,8 +1551,7 @@ ppc_insert_operand (insn, operand, val, file, line) as_bad_where (file, line, errmsg); } else - insn |= (((long) val & ((1 << operand->bits) - 1)) - << operand->shift); + insn |= ((long) val & operand->bitm) << operand->shift; return insn; } @@ -1496,9 +1560,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; @@ -1676,8 +1738,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; @@ -1732,8 +1793,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"; @@ -1747,14 +1807,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; @@ -1857,9 +1916,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; @@ -1904,7 +1961,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; @@ -1987,8 +2044,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; @@ -2052,8 +2108,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; @@ -2099,8 +2154,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; @@ -2724,16 +2778,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; @@ -2771,7 +2823,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; } @@ -2802,9 +2854,7 @@ ppc_macro (str, macro) /* For ELF, add support for SHF_EXCLUDE and SHT_ORDERED. */ int -ppc_section_letter (letter, ptr_msg) - int letter; - char **ptr_msg; +ppc_section_letter (int letter, char **ptr_msg) { if (letter == 'e') return SHF_EXCLUDE; @@ -2814,9 +2864,7 @@ ppc_section_letter (letter, ptr_msg) } int -ppc_section_word (str, len) - char *str; - size_t len; +ppc_section_word (char *str, size_t len) { if (len == 7 && strncmp (str, "exclude", 7) == 0) return SHF_EXCLUDE; @@ -2825,9 +2873,7 @@ ppc_section_word (str, len) } 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; @@ -2836,10 +2882,7 @@ ppc_section_type (str, len) } int -ppc_section_flags (flags, attr, type) - int flags; - int attr; - int type; +ppc_section_flags (int flags, int attr, int type) { if (type == SHT_ORDERED) flags |= SEC_ALLOC | SEC_LOAD | SEC_SORT_ENTRIES; @@ -2858,8 +2901,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 != '\"') { @@ -2903,8 +2945,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; @@ -3058,8 +3099,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; @@ -3094,9 +3134,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); @@ -3196,8 +3234,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; @@ -3221,8 +3258,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; @@ -3256,8 +3292,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; @@ -3275,8 +3310,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; @@ -3298,8 +3332,7 @@ ppc_lglobl (ignore) 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; @@ -3334,8 +3367,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; @@ -3461,8 +3493,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; @@ -3555,8 +3586,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; @@ -3591,8 +3621,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; @@ -3616,8 +3645,7 @@ ppc_ef (ignore) is encountered. */ static void -ppc_biei (ei) - int ei; +ppc_biei (int ei) { static symbolS *last_biei; @@ -3671,8 +3699,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; @@ -3707,8 +3734,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; @@ -3732,8 +3758,7 @@ ppc_es (ignore) line number. */ static void -ppc_bb (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_bb (int ignore ATTRIBUTE_UNUSED) { symbolS *sym; @@ -3759,8 +3784,7 @@ ppc_bb (ignore) line number. */ static void -ppc_eb (ignore) - int ignore ATTRIBUTE_UNUSED; +ppc_eb (int ignore ATTRIBUTE_UNUSED) { symbolS *sym; @@ -3784,8 +3808,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; @@ -3807,8 +3830,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; @@ -3827,8 +3849,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); @@ -3874,8 +3895,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); @@ -3883,8 +3903,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; @@ -3927,8 +3946,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 @@ -4014,8 +4032,7 @@ 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 @@ -4078,8 +4095,7 @@ 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; @@ -4100,8 +4116,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; @@ -4113,8 +4128,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; @@ -4145,8 +4159,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) { @@ -4180,8 +4193,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) { @@ -4217,8 +4229,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) { @@ -4248,8 +4259,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) { @@ -4275,8 +4285,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); @@ -4290,8 +4299,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; @@ -4343,14 +4351,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; @@ -4473,8 +4480,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; @@ -4562,7 +4568,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; @@ -4606,7 +4612,7 @@ ppc_pe_section (ignore) flags |= IMAGE_SCN_ALIGN_64BYTES; align = 6; break; - +#endif default: as_bad (_("unknown section attribute '%c'"), *input_line_pointer); @@ -4632,12 +4638,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; @@ -4659,8 +4663,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) { @@ -4685,8 +4688,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; } @@ -4701,8 +4703,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; @@ -4739,8 +4740,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; @@ -4828,8 +4828,7 @@ 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) { @@ -4859,8 +4858,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; @@ -5123,7 +5121,7 @@ ppc_frob_symbol (sym) absolute symbols. */ void -ppc_adjust_symtab () +ppc_adjust_symtab (void) { symbolS *sym; @@ -5169,8 +5167,7 @@ ppc_adjust_symtab () turn. */ void -ppc_frob_section (sec) - asection *sec; +ppc_frob_section (asection *sec) { static bfd_vma vma = 0; @@ -5187,10 +5184,7 @@ ppc_frob_section (sec) 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]; @@ -5242,10 +5236,7 @@ md_atof (type, litp, sizep) 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); @@ -5256,21 +5247,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; @@ -5279,10 +5271,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 (); } @@ -5290,8 +5281,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; } @@ -5302,9 +5292,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; } @@ -5317,8 +5305,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); @@ -5443,8 +5430,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 @@ -5469,8 +5455,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. */ @@ -5495,8 +5480,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 @@ -5510,6 +5494,47 @@ 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) + { + /* For power6, we want the last nop to be a group terminating + one, "ori 1,1,0". 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; + } + + 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 @@ -5520,10 +5545,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; @@ -5580,7 +5602,7 @@ 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 @@ -5618,11 +5640,11 @@ md_apply_fix (fixP, valP, seg) 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; @@ -5633,11 +5655,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; @@ -5649,7 +5671,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)) @@ -6047,9 +6069,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; @@ -6072,13 +6092,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; |