X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-hppa.c;h=8ae5a57e9039756f9a8c295f7f5b44baa72ad48e;hb=7f3dfb9cf74da197cfe71fb0490a90613269ca0f;hp=39da02ed17ee96cf96abd1f52debe100d214196a;hpb=85c77c383f623ece2c4cbb485bf74848e766edf3;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c index 39da02ed17..8ae5a57e90 100644 --- a/gas/config/tc-hppa.c +++ b/gas/config/tc-hppa.c @@ -1,6 +1,6 @@ /* tc-hppa.c -- Assemble for the PA Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003 Free Software Foundation, Inc. + 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -16,8 +16,8 @@ You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ /* HP PA-RISC support was contributed by the Center for Software Science at the University of Utah. */ @@ -43,7 +43,7 @@ error only one of OBJ_ELF and OBJ_SOM can be defined #ifdef OBJ_ELF #include "dwarf2dbg.h" -/* A "convient" place to put object file dependencies which do +/* A "convenient" place to put object file dependencies which do not need to be seen outside of tc-hppa.c. */ /* Object file formats specify relocation types. */ @@ -363,6 +363,9 @@ struct default_subspace_dict /* Nonzero if this subspace contains only code. */ char code_only; + /* Nonzero if this is a comdat subspace. */ + char comdat; + /* Nonzero if this is a common subspace. */ char common; @@ -490,7 +493,7 @@ struct selector_entry static void pa_check_current_space_and_subspace PARAMS ((void)); #endif -#if !(defined (OBJ_ELF) && defined (TE_LINUX)) +#if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD))) static void pa_text PARAMS ((int)); static void pa_data PARAMS ((int)); static void pa_comm PARAMS ((int)); @@ -544,7 +547,7 @@ static int need_pa11_opcode PARAMS ((void)); static int pa_parse_number PARAMS ((char **, int)); static label_symbol_struct *pa_get_label PARAMS ((void)); #ifdef OBJ_SOM -static int log2 PARAMS ((int)); +static int exact_log2 PARAMS ((int)); static void pa_compiler PARAMS ((int)); static void pa_align PARAMS ((int)); static void pa_space PARAMS ((int)); @@ -555,13 +558,13 @@ static sd_chain_struct *create_new_space PARAMS ((char *, int, int, asection *, int)); static ssd_chain_struct *create_new_subspace PARAMS ((sd_chain_struct *, char *, int, int, - int, int, int, + int, int, int, int, int, int, int, int, int, asection *)); static ssd_chain_struct *update_subspace PARAMS ((sd_chain_struct *, char *, int, int, int, int, int, int, int, - int, int, int, + int, int, int, int, asection *)); static sd_chain_struct *is_defined_space PARAMS ((char *)); static ssd_chain_struct *is_defined_subspace PARAMS ((char *)); @@ -571,7 +574,6 @@ static ssd_chain_struct *pa_subsegment_to_subspace PARAMS ((asection *, static sd_chain_struct *pa_find_space_by_number PARAMS ((int)); static unsigned int pa_subspace_start PARAMS ((sd_chain_struct *, int)); static sd_chain_struct *pa_parse_space_stmt PARAMS ((char *, int)); -static int pa_next_subseg PARAMS ((sd_chain_struct *)); static void pa_spaces_begin PARAMS ((void)); #endif static void pa_ip PARAMS ((char *)); @@ -596,7 +598,7 @@ static void pa_vtable_entry PARAMS ((int)); static void pa_vtable_inherit PARAMS ((int)); #endif -/* File and gloally scoped variable declarations. */ +/* File and globally scoped variable declarations. */ #ifdef OBJ_SOM /* Root and final entry in the space chain. */ @@ -647,7 +649,7 @@ const pseudo_typeS md_pseudo_table[] = {"byte", pa_cons, 1}, {"call", pa_call, 0}, {"callinfo", pa_callinfo, 0}, -#if defined (OBJ_ELF) && defined (TE_LINUX) +#if defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD)) {"code", obj_elf_text, 0}, #else {"code", pa_text, 0}, @@ -657,14 +659,14 @@ const pseudo_typeS md_pseudo_table[] = {"compiler", pa_compiler, 0}, #endif {"copyright", pa_copyright, 0}, -#if !(defined (OBJ_ELF) && defined (TE_LINUX)) +#if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD))) {"data", pa_data, 0}, #endif {"double", pa_float_cons, 'd'}, {"dword", pa_cons, 8}, {"end", pa_end, 0}, {"end_brtab", pa_brtab, 0}, -#if !(defined (OBJ_ELF) && defined (TE_LINUX)) +#if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD))) {"end_try", pa_try, 0}, #endif {"enter", pa_enter, 0}, @@ -705,7 +707,7 @@ const pseudo_typeS md_pseudo_table[] = #ifdef OBJ_SOM {"subspa", pa_subspace, 0}, #endif -#if !(defined (OBJ_ELF) && defined (TE_LINUX)) +#if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD))) {"text", pa_text, 0}, #endif {"version", pa_version, 0}, @@ -748,7 +750,7 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; static struct pa_it the_insn; -/* Points to the end of an expression just parsed by get_expressoin +/* Points to the end of an expression just parsed by get_expression and friends. FIXME. This shouldn't be handled with a file-global variable. */ static char *expr_end; @@ -769,11 +771,15 @@ static label_symbol_struct *label_symbols_rootp = NULL; /* Holds the last field selector. */ static int hppa_field_selector; -/* Nonzero when strict syntax checking is enabled. Zero otherwise. +/* Nonzero when strict matching is enabled. Zero otherwise. - Each opcode in the table has a flag which indicates whether or not - strict syntax checking should be enabled for that instruction. */ -static int strict = 0; + Each opcode in the table has a flag which indicates whether or + not strict matching should be enabled for that instruction. + + Mainly, strict causes errors to be ignored when a match failure + occurs. However, it also affects the parsing of register fields + by pa_parse_number. */ +static int strict; /* pa_parse_number returns values in `pa_number'. Mostly pa_parse_number is used to return a register number, with floating @@ -809,6 +815,7 @@ static int print_errors = 1; %r26 - %r23 have %arg0 - %arg3 as synonyms %r28 - %r29 have %ret0 - %ret1 as synonyms + %fr4 - %fr7 have %farg0 - %farg3 as synonyms %r30 has %sp as a synonym %r27 has %dp as a synonym %r2 has %rp as a synonym @@ -852,6 +859,10 @@ static const struct pd_reg pre_defined_registers[] = {"%dp", 27}, {"%eiem", 15}, {"%eirr", 23}, + {"%farg0", 4 + FP_REG_BASE}, + {"%farg1", 5 + FP_REG_BASE}, + {"%farg2", 6 + FP_REG_BASE}, + {"%farg3", 7 + FP_REG_BASE}, {"%fr0", 0 + FP_REG_BASE}, {"%fr0l", 0 + FP_REG_BASE}, {"%fr0r", 0 + FP_REG_BASE + FP_REG_RSEL}, @@ -948,6 +959,7 @@ static const struct pd_reg pre_defined_registers[] = {"%fr9", 9 + FP_REG_BASE}, {"%fr9l", 9 + FP_REG_BASE}, {"%fr9r", 9 + FP_REG_BASE + FP_REG_RSEL}, + {"%fret", 4}, {"%hta", 25}, {"%iir", 19}, {"%ior", 21}, @@ -1013,6 +1025,14 @@ static const struct pd_reg pre_defined_registers[] = {"%sr5", 5}, {"%sr6", 6}, {"%sr7", 7}, + {"%t1", 22}, + {"%t2", 21}, + {"%t3", 20}, + {"%t4", 19}, + {"%tf1", 11}, + {"%tf2", 10}, + {"%tf3", 9}, + {"%tf4", 8}, {"%tr0", 24}, {"%tr1", 25}, {"%tr2", 26}, @@ -1104,12 +1124,12 @@ static const struct selector_entry selector_table[] = static struct default_subspace_dict pa_def_subspaces[] = { - {"$CODE$", 1, 1, 1, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, SUBSEG_CODE}, - {"$DATA$", 1, 1, 0, 0, 0, 0, 24, 0x1f, 1, 8, 1, 1, SUBSEG_DATA}, - {"$LIT$", 1, 1, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, SUBSEG_LIT}, - {"$MILLICODE$", 1, 1, 0, 0, 0, 0, 8, 0x2c, 0, 8, 0, 0, SUBSEG_MILLI}, - {"$BSS$", 1, 1, 0, 0, 0, 1, 80, 0x1f, 1, 8, 1, 1, SUBSEG_BSS}, - {NULL, 0, 1, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, 0, 0} + {"$CODE$", 1, 1, 1, 0, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, SUBSEG_CODE}, + {"$DATA$", 1, 1, 0, 0, 0, 0, 0, 24, 0x1f, 1, 8, 1, 1, SUBSEG_DATA}, + {"$LIT$", 1, 1, 0, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, SUBSEG_LIT}, + {"$MILLICODE$", 1, 1, 0, 0, 0, 0, 0, 8, 0x2c, 0, 8, 0, 0, SUBSEG_MILLI}, + {"$BSS$", 1, 1, 0, 0, 0, 0, 1, 80, 0x1f, 1, 8, 1, 1, SUBSEG_BSS}, + {NULL, 0, 1, 0, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, 0, 0} }; static struct default_space_dict pa_def_spaces[] = @@ -1145,7 +1165,7 @@ static struct default_space_dict pa_def_spaces[] = continue; \ } -/* Simple range checking for FIELD againt HIGH and LOW bounds. +/* Simple range checking for FIELD against HIGH and LOW bounds. IGNORE is used to suppress the error message. */ #define CHECK_FIELD(FIELD, HIGH, LOW, IGNORE) \ @@ -1159,7 +1179,7 @@ static struct default_space_dict pa_def_spaces[] = } \ } -/* Variant of CHECK_FIELD for use in md_apply_fix3 and other places where +/* Variant of CHECK_FIELD for use in md_apply_fix and other places where the current file and line number are not valid. */ #define CHECK_FIELD_WHERE(FIELD, HIGH, LOW, FILENAME, LINE) \ @@ -1173,7 +1193,7 @@ static struct default_space_dict pa_def_spaces[] = } \ } -/* Simple alignment checking for FIELD againt ALIGN (a power of two). +/* Simple alignment checking for FIELD against ALIGN (a power of two). IGNORE is used to suppress the error message. */ #define CHECK_ALIGN(FIELD, ALIGN, IGNORE) \ @@ -1271,6 +1291,10 @@ pa_define_label (symbol) label_symbols_rootp = label_chain; } + +#ifdef OBJ_ELF + dwarf2_emit_label (symbol); +#endif } /* Removes a label definition for the current space. @@ -1386,6 +1410,8 @@ cons_fix_new_hppa (frag, where, size, exp) /* Get a base relocation type. */ if (is_DP_relative (*exp)) rel_type = R_HPPA_GOTOFF; + else if (is_PC_relative (*exp)) + rel_type = R_HPPA_PCREL_CALL; else if (is_complex (*exp)) rel_type = R_HPPA_COMPLEX; else @@ -1530,7 +1556,7 @@ md_assemble (str) /* Assemble the instruction. Results are saved into "the_insn". */ pa_ip (str); - /* Get somewhere to put the assembled instrution. */ + /* Get somewhere to put the assembled instruction. */ to = frag_more (4); /* Output the opcode. */ @@ -1596,7 +1622,8 @@ pa_ip (str) break; default: - as_fatal (_("Unknown opcode: `%s'"), str); + as_bad (_("Unknown opcode: `%s'"), str); + return; } /* Look up the opcode in the has table. */ @@ -1623,21 +1650,9 @@ pa_ip (str) the_insn.reloc = R_HPPA_NONE; - /* If this instruction is specific to a particular architecture, - then set a new architecture. */ - /* But do not automatically promote to pa2.0. The automatic promotion - crud is for compatability with HP's old assemblers only. */ - if (insn->arch < 20 + if (insn->arch >= pa20 && bfd_get_mach (stdoutput) < insn->arch) - { - if (!bfd_set_arch_mach (stdoutput, bfd_arch_hppa, insn->arch)) - as_warn (_("could not update architecture and machine")); - } - else if (bfd_get_mach (stdoutput) < insn->arch) - { - match = FALSE; - goto failed; - } + goto failed; /* Build the opcode, checking as we go to make sure that the operands match. */ @@ -1832,9 +1847,9 @@ pa_ip (str) else if ((strncasecmp (s, "s ", 2) == 0) || (strncasecmp (s, "s,", 2) == 0)) uu = 1; - /* When in strict mode this is a match failure. */ else if (strict) { + /* This is a match failure. */ s--; break; } @@ -1860,28 +1875,25 @@ pa_ip (str) int m = 0; if (*s == ',') { - int found = 0; s++; if (strncasecmp (s, "ma", 2) == 0) { a = 0; m = 1; - found = 1; + s += 2; } else if (strncasecmp (s, "mb", 2) == 0) { a = 1; m = 1; - found = 1; + s += 2; } - - /* When in strict mode, pass through for cache op. */ - if (!found && strict) + else if (strict) + /* This is a match failure. */ s--; else { - if (!found) - as_bad (_("Invalid Short Load/Store Completer.")); + as_bad (_("Invalid Short Load/Store Completer.")); s += 2; } } @@ -1934,7 +1946,7 @@ pa_ip (str) a = 0; else if (strncasecmp (s, "e", 1) == 0) a = 1; - /* When in strict mode this is a match failure. */ + /* In strict mode, this is a match failure. */ else if (strict) { s--; @@ -2357,7 +2369,6 @@ pa_ip (str) } else if (*s == '*') break; - name = s; name = s; while (*s != ',' && *s != ' ' && *s != '\t') @@ -2419,7 +2430,7 @@ pa_ip (str) flag = 1; } /* ",*" is a valid condition. */ - else if (*args == 'a') + else if (*args == 'a' || *name) as_bad (_("Invalid Add Condition: %s"), name); *s = c; } @@ -2525,7 +2536,6 @@ pa_ip (str) } else if (*s == '*') break; - name = s; name = s; while (*s != ',' && *s != ' ' && *s != '\t') @@ -2587,7 +2597,7 @@ pa_ip (str) flag = 1; } /* ",*" is a valid condition. */ - else if (*args != 'S') + else if (*args != 'S' || *name) as_bad (_("Invalid Compare/Subtract Condition: %s"), name); *s = c; @@ -2710,7 +2720,7 @@ pa_ip (str) flag = 1; } /* ",*" is a valid condition. */ - else if (*args != 'L') + else if (*args != 'L' || *name) as_bad (_("Invalid Logical Instruction Condition.")); *s = c; } @@ -2765,7 +2775,7 @@ pa_ip (str) continue; } /* ",*" is a valid condition. */ - else if (*args != 'X') + else if (*args != 'X' || *name) as_bad (_("Invalid Shift/Extract/Deposit Condition.")); *s = c; } @@ -2877,7 +2887,7 @@ pa_ip (str) s += 3; } /* ",*" is a valid condition. */ - else if (*args != 'U') + else if (*args != 'U' || (*s != ' ' && *s != '\t')) as_bad (_("Invalid Unit Instruction Condition.")); } opcode |= cmpltr << 13; @@ -3060,6 +3070,8 @@ pa_ip (str) /* Handle 14 bit immediate, shifted left three times. */ case '#': + if (bfd_get_mach (stdoutput) != pa20) + break; the_insn.field_selector = pa_chk_field_selector (&s); get_expression (s); s = expr_end; @@ -3946,6 +3958,17 @@ pa_ip (str) break; } + /* If this instruction is specific to a particular architecture, + then set a new architecture. This automatic promotion crud is + for compatibility with HP's old assemblers only. */ + if (match == TRUE + && bfd_get_mach (stdoutput) < insn->arch + && !bfd_set_arch_mach (stdoutput, bfd_arch_hppa, insn->arch)) + { + as_warn (_("could not update architecture and machine")); + match = FALSE; + } + failed: /* Check if the args matched. */ if (!match) @@ -4408,12 +4431,12 @@ md_undefined_symbol (name) /* Apply a fixup to an instruction. */ void -md_apply_fix3 (fixP, valP, seg) +md_apply_fix (fixP, valP, seg) fixS *fixP; valueT *valP; segT seg ATTRIBUTE_UNUSED; { - unsigned char *buf; + char *fixpos; struct hppa_fix_struct *hppa_fixP; offsetT new_val; int insn, val, fmt; @@ -4447,8 +4470,7 @@ md_apply_fix3 (fixP, valP, seg) if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) fixP->fx_done = 1; - /* There should have been an HPPA specific fixup associated - with the GAS fixup. */ + /* There should be a HPPA specific fixup associated with the GAS fixup. */ hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data; if (hppa_fixP == NULL) { @@ -4458,8 +4480,16 @@ md_apply_fix3 (fixP, valP, seg) return; } - buf = (unsigned char *) (fixP->fx_frag->fr_literal + fixP->fx_where); - insn = bfd_get_32 (stdoutput, buf); + fixpos = fixP->fx_frag->fr_literal + fixP->fx_where; + + if (fixP->fx_size != 4 || hppa_fixP->fx_r_format == 32) + { + /* Handle constant output. */ + number_to_chars_bigendian (fixpos, *valP, fixP->fx_size); + return; + } + + insn = bfd_get_32 (stdoutput, fixpos); fmt = bfd_hppa_insn2fmt (stdoutput, insn); /* If there is a symbol associated with this fixup, then it's something @@ -4629,7 +4659,7 @@ md_apply_fix3 (fixP, valP, seg) } /* Insert the relocation. */ - bfd_put_32 (stdoutput, insn, buf); + bfd_put_32 (stdoutput, insn, fixpos); } /* Exactly what point is a PC-relative offset relative TO? @@ -4834,7 +4864,7 @@ pa_parse_number (s, is_float) /* There is where we'd come for an undefined symbol or for an empty string. For an empty string we will return zero. That's a concession made for - compatability with the braindamaged HP assemblers. */ + compatibility with the braindamaged HP assemblers. */ if (*name == 0) num = 0; else @@ -5205,11 +5235,11 @@ pa_get_absolute_expression (insn, strp) expression (&insn->exp); /* This is not perfect, but is a huge improvement over doing nothing. - The PA assembly syntax is ambigious in a variety of ways. Consider + The PA assembly syntax is ambiguous in a variety of ways. Consider this string "4 %r5" Is that the number 4 followed by the register r5, or is that 4 MOD r5? - If we get a modulo expresion When looking for an absolute, we try + If we get a modulo expression when looking for an absolute, we try again cutting off the input string at the first whitespace character. */ if (insn->exp.X_op == O_modulus) { @@ -5347,7 +5377,7 @@ pa_parse_nullif (s) } /* Parse a non-negated compare/subtract completer returning the - number (for encoding in instrutions) of the given completer. */ + number (for encoding in instructions) of the given completer. */ static int pa_parse_nonneg_cmpsub_cmpltr (s) @@ -5418,7 +5448,7 @@ pa_parse_nonneg_cmpsub_cmpltr (s) } /* Parse a negated compare/subtract completer returning the - number (for encoding in instrutions) of the given completer. */ + number (for encoding in instructions) of the given completer. */ static int pa_parse_neg_cmpsub_cmpltr (s) @@ -5493,7 +5523,7 @@ pa_parse_neg_cmpsub_cmpltr (s) } /* Parse a 64 bit compare and branch completer returning the number (for - encoding in instrutions) of the given completer. + encoding in instructions) of the given completer. Nonnegated comparisons are returned as 0-7, negated comparisons are returned as 8-15. */ @@ -5590,7 +5620,7 @@ pa_parse_cmpb_64_cmpltr (s) } /* Parse a 64 bit compare immediate and branch completer returning the number - (for encoding in instrutions) of the given completer. */ + (for encoding in instructions) of the given completer. */ static int pa_parse_cmpib_64_cmpltr (s) @@ -5652,7 +5682,7 @@ pa_parse_cmpib_64_cmpltr (s) } /* Parse a non-negated addition completer returning the number - (for encoding in instrutions) of the given completer. */ + (for encoding in instructions) of the given completer. */ static int pa_parse_nonneg_add_cmpltr (s) @@ -5722,7 +5752,7 @@ pa_parse_nonneg_add_cmpltr (s) } /* Parse a negated addition completer returning the number - (for encoding in instrutions) of the given completer. */ + (for encoding in instructions) of the given completer. */ static int pa_parse_neg_add_cmpltr (s) @@ -5796,7 +5826,7 @@ pa_parse_neg_add_cmpltr (s) } /* Parse a 64 bit wide mode add and branch completer returning the number (for - encoding in instrutions) of the given completer. */ + encoding in instructions) of the given completer. */ static int pa_parse_addb_64_cmpltr (s) @@ -5912,8 +5942,8 @@ pa_align (bytes) /* If bytes is a power of 2, then update the current subspace's alignment if necessary. */ - if (log2 (bytes) != -1) - record_alignment (current_subspace->ssd_seg, log2 (bytes)); + if (exact_log2 (bytes) != -1) + record_alignment (current_subspace->ssd_seg, exact_log2 (bytes)); } #endif @@ -5923,10 +5953,7 @@ static void pa_block (z) int z ATTRIBUTE_UNUSED; { - char *p; - long int temp_fill; unsigned int temp_size; - unsigned int i; #ifdef OBJ_SOM /* We must have a valid space and subspace. */ @@ -5935,20 +5962,16 @@ pa_block (z) temp_size = get_absolute_expression (); - /* Always fill with zeros, that's what the HP assembler does. */ - temp_fill = 0; - - p = frag_var (rs_fill, (int) temp_size, (int) temp_size, - (relax_substateT) 0, (symbolS *) 0, (offsetT) 1, NULL); - memset (p, 0, temp_size); - - /* Convert 2 bytes at a time. */ - - for (i = 0; i < temp_size; i += 2) + if (temp_size > 0x3FFFFFFF) { - md_number_to_chars (p + i, - (valueT) temp_fill, - (int) ((temp_size - i) > 2 ? 2 : (temp_size - i))); + as_bad (_("Argument to .BLOCK/.BLOCKZ must be between 0 and 0x3fffffff")); + temp_size = 0; + } + else + { + /* Always fill with zeros, that's what the HP assembler does. */ + char *p = frag_var (rs_fill, 1, 1, 0, NULL, temp_size, NULL); + *p = 0; } pa_undefine_label (); @@ -5963,7 +5986,7 @@ pa_brtab (begin) { #ifdef OBJ_SOM - /* The BRTAB relocations are only availble in SOM (to denote + /* The BRTAB relocations are only available in SOM (to denote the beginning and end of branch tables). */ char *where = frag_more (0); @@ -5989,7 +6012,7 @@ pa_try (begin) if (! begin) expression (&exp); - /* The TRY relocations are only availble in SOM (to denote + /* The TRY relocations are only available in SOM (to denote the beginning and end of exception handling regions). */ fix_new_hppa (frag_now, where - frag_now->fr_literal, 0, @@ -6306,7 +6329,7 @@ pa_callinfo (unused) demand_empty_rest_of_line (); } -#if !(defined (OBJ_ELF) && defined (TE_LINUX)) +#if !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD))) /* Switch to the text space. Like s_text, but delete our label when finished. */ static void @@ -6375,8 +6398,9 @@ pa_comm (unused) if (symbol) { + symbol_get_bfdsym (symbol)->flags |= BSF_OBJECT; S_SET_VALUE (symbol, size); - S_SET_SEGMENT (symbol, bfd_und_section_ptr); + S_SET_SEGMENT (symbol, bfd_com_section_ptr); S_SET_EXTERNAL (symbol); /* colon() has already set the frag to the current location in the @@ -6386,7 +6410,7 @@ pa_comm (unused) } demand_empty_rest_of_line (); } -#endif /* !(defined (OBJ_ELF) && defined (TE_LINUX)) */ +#endif /* !(defined (OBJ_ELF) && (defined (TE_LINUX) || defined (TE_NetBSD))) */ /* Process a .END pseudo-op. */ @@ -6412,7 +6436,7 @@ pa_enter (unused) } /* Process a .ENTRY pseudo-op. .ENTRY marks the beginning of the - procesure. */ + procedure. */ static void pa_entry (unused) int unused ATTRIBUTE_UNUSED; @@ -6770,7 +6794,7 @@ pa_type_args (symbolP, is_export) #endif *input_line_pointer = c; } - /* Privelege level. */ + /* Privilege level. */ else if ((strncasecmp (name, "priv_lev", 8)) == 0) { p = input_line_pointer; @@ -6825,7 +6849,7 @@ pa_import (unused) } else { - /* Sigh. To be compatable with the HP assembler and to help + /* Sigh. To be compatible with the HP assembler and to help poorly written assembly code, we assign a type based on the current segment. Note only BSF_FUNCTION really matters, we do not need to set the full SYMBOL_TYPE_* info. */ @@ -7054,7 +7078,7 @@ pa_proc (unused) demand_empty_rest_of_line (); } -/* Process the syntatical end of a procedure. Make sure all the +/* Process the syntactical end of a procedure. Make sure all the appropriate pseudo-ops were found within the procedure. */ static void @@ -7133,7 +7157,7 @@ pa_procend (unused) return log2 (VALUE). Else return -1. */ static int -log2 (value) +exact_log2 (value) int value; { int shift = 0; @@ -7263,7 +7287,7 @@ pa_parse_space_stmt (space_name, create_flag) /* If create_flag is nonzero, then create the new space with the attributes computed above. Else set the values in an already existing space -- this can only happen for - the first occurence of a built-in space. */ + the first occurrence of a built-in space. */ if (create_flag) space = create_new_space (space_name, spnum, loadable, defined, private, sort, seg, 1); @@ -7440,7 +7464,7 @@ pa_subspace (create_new) int create_new; { char *name, *ss_name, c; - char loadable, code_only, common, dup_common, zero, sort; + char loadable, code_only, comdat, common, dup_common, zero, sort; int i, access, space_index, alignment, quadrant, applicable, flags; sd_chain_struct *space; ssd_chain_struct *ssd; @@ -7466,6 +7490,7 @@ pa_subspace (create_new) sort = 0; access = 0x7f; loadable = 1; + comdat = 0; common = 0; dup_common = 0; code_only = 0; @@ -7500,6 +7525,7 @@ pa_subspace (create_new) if (strcasecmp (pa_def_subspaces[i].name, ss_name) == 0) { loadable = pa_def_subspaces[i].loadable; + comdat = pa_def_subspaces[i].comdat; common = pa_def_subspaces[i].common; dup_common = pa_def_subspaces[i].dup_common; code_only = pa_def_subspaces[i].code_only; @@ -7535,7 +7561,7 @@ pa_subspace (create_new) *input_line_pointer = c; input_line_pointer++; alignment = get_absolute_expression (); - if (log2 (alignment) == -1) + if (exact_log2 (alignment) == -1) { as_bad (_("Alignment must be a power of 2")); alignment = 1; @@ -7563,6 +7589,11 @@ pa_subspace (create_new) *input_line_pointer = c; loadable = 0; } + else if ((strncasecmp (name, "comdat", 6) == 0)) + { + *input_line_pointer = c; + comdat = 1; + } else if ((strncasecmp (name, "common", 6) == 0)) { *input_line_pointer = c; @@ -7595,8 +7626,17 @@ pa_subspace (create_new) flags |= (SEC_ALLOC | SEC_LOAD); if (code_only) flags |= SEC_CODE; - if (common || dup_common) - flags |= SEC_IS_COMMON; + + /* These flags are used to implement various flavors of initialized + common. The SOM linker discards duplicate subspaces when they + have the same "key" symbol name. This support is more like + GNU linkonce than BFD common. Further, pc-relative relocations + are converted to section relative relocations in BFD common + sections. This complicates the handling of relocations in + common sections containing text and isn't currently supported + correctly in the SOM BFD backend. */ + if (comdat || common || dup_common) + flags |= SEC_LINK_ONCE; flags |= SEC_RELOC | SEC_HAS_CONTENTS; @@ -7627,7 +7667,7 @@ pa_subspace (create_new) bfd_set_section_flags (stdoutput, section, applicable); /* Record any alignment request for this section. */ - record_alignment (section, log2 (alignment)); + record_alignment (section, exact_log2 (alignment)); /* Set the starting offset for this section. */ bfd_set_section_vma (stdoutput, section, @@ -7638,16 +7678,16 @@ pa_subspace (create_new) if (ssd) current_subspace = update_subspace (space, ss_name, loadable, - code_only, common, dup_common, - sort, zero, access, space_index, - alignment, quadrant, + code_only, comdat, common, + dup_common, sort, zero, access, + space_index, alignment, quadrant, section); else current_subspace = create_new_subspace (space, ss_name, loadable, - code_only, common, + code_only, comdat, common, dup_common, zero, sort, access, space_index, - alignment, quadrant, section); + alignment, quadrant, section); demand_empty_rest_of_line (); current_subspace->ssd_seg = section; @@ -7768,6 +7808,7 @@ pa_spaces_begin () create_new_subspace (space, name, pa_def_subspaces[i].loadable, pa_def_subspaces[i].code_only, + pa_def_subspaces[i].comdat, pa_def_subspaces[i].common, pa_def_subspaces[i].dup_common, pa_def_subspaces[i].zero, @@ -7789,7 +7830,7 @@ create_new_space (name, spnum, loadable, defined, private, sort, seg, user_defined) char *name; int spnum; - int loadable; + int loadable ATTRIBUTE_UNUSED; int defined; int private; int sort; @@ -7869,16 +7910,19 @@ create_new_space (name, spnum, loadable, defined, private, order as defined by the SORT entries. */ static ssd_chain_struct * -create_new_subspace (space, name, loadable, code_only, common, +create_new_subspace (space, name, loadable, code_only, comdat, common, dup_common, is_zero, sort, access, space_index, alignment, quadrant, seg) sd_chain_struct *space; char *name; - int loadable, code_only, common, dup_common, is_zero; + int loadable ATTRIBUTE_UNUSED; + int code_only ATTRIBUTE_UNUSED; + int comdat, common, dup_common; + int is_zero ATTRIBUTE_UNUSED; int sort; int access; - int space_index; - int alignment; + int space_index ATTRIBUTE_UNUSED; + int alignment ATTRIBUTE_UNUSED; int quadrant; asection *seg; { @@ -7931,8 +7975,8 @@ create_new_subspace (space, name, loadable, code_only, common, } #ifdef obj_set_subsection_attributes - obj_set_subsection_attributes (seg, space->sd_seg, access, - sort, quadrant); + obj_set_subsection_attributes (seg, space->sd_seg, access, sort, + quadrant, comdat, common, dup_common); #endif return chain_entry; @@ -7942,19 +7986,20 @@ create_new_subspace (space, name, loadable, code_only, common, various arguments. Return the modified subspace chain entry. */ static ssd_chain_struct * -update_subspace (space, name, loadable, code_only, common, dup_common, sort, - zero, access, space_index, alignment, quadrant, section) +update_subspace (space, name, loadable, code_only, comdat, common, dup_common, + sort, zero, access, space_index, alignment, quadrant, section) sd_chain_struct *space; char *name; - int loadable; - int code_only; + int loadable ATTRIBUTE_UNUSED; + int code_only ATTRIBUTE_UNUSED; + int comdat; int common; int dup_common; - int zero; + int zero ATTRIBUTE_UNUSED; int sort; int access; - int space_index; - int alignment; + int space_index ATTRIBUTE_UNUSED; + int alignment ATTRIBUTE_UNUSED; int quadrant; asection *section; { @@ -7963,8 +8008,8 @@ update_subspace (space, name, loadable, code_only, common, dup_common, sort, chain_entry = is_defined_subspace (name); #ifdef obj_set_subsection_attributes - obj_set_subsection_attributes (section, space->sd_seg, access, - sort, quadrant); + obj_set_subsection_attributes (section, space->sd_seg, access, sort, + quadrant, comdat, common, dup_common); #endif return chain_entry; @@ -8016,9 +8061,14 @@ pa_segment_to_space (seg) return NULL; } -/* Return the space chain entry for the subspace with the name NAME or - NULL if no such subspace exists. +/* Return the first space chain entry for the subspace with the name + NAME or NULL if no such subspace exists. + When there are multiple subspaces with the same name, switching to + the first (i.e., default) subspace is preferable in most situations. + For example, it wouldn't be desirable to merge COMDAT data with non + COMDAT data. + Uses a linear search through all the spaces and subspaces, this may not be appropriate if we ever being placing each function in its own subspace. */ @@ -8124,16 +8174,6 @@ pa_subspace_start (space, quadrant) return 0; return 0; } - -/* FIXME. Needs documentation. */ -static int -pa_next_subseg (space) - sd_chain_struct *space; -{ - - space->sd_last_subseg++; - return space->sd_last_subseg; -} #endif /* Helper function for pa_stringer. Used to find the end of @@ -8356,28 +8396,20 @@ pa_lsym (unused) any fixup which creates entries in the DLT (eg they use "T" field selectors). - Reject reductions involving symbols with external scope; such - reductions make life a living hell for object file editors. - - FIXME. Also reject R_HPPA relocations which are 32bits wide in - the code space. The SOM BFD backend doesn't know how to pull the - right bits out of an instruction. */ + ??? Reject reductions involving symbols with external scope; such + reductions make life a living hell for object file editors. */ int hppa_fix_adjustable (fixp) fixS *fixp; { +#ifdef OBJ_ELF reloc_type code; +#endif struct hppa_fix_struct *hppa_fix; hppa_fix = (struct hppa_fix_struct *) fixp->tc_fix_data; -#ifdef OBJ_SOM - /* Reject reductions of symbols in 32bit relocs. */ - if (fixp->fx_r_type == R_HPPA && hppa_fix->fx_r_format == 32) - return 0; -#endif - #ifdef OBJ_ELF /* LR/RR selectors are implicitly used for a number of different relocation types. We must ensure that none of these types are adjusted (see below) @@ -8451,7 +8483,7 @@ hppa_fix_adjustable (fixp) . RR%sect+4092 == (R%sect)+4092 . RR%sect+4096 == (R%sect)-4096 and the last address loses because rounding the addend to 8k - mutiples takes us up to 8192 with an offset of -4096. + multiples takes us up to 8192 with an offset of -4096. In cases where the LR% expression is identical to the RR% one we will never have a problem, but is so happens that gcc rounds