X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-hppa.c;h=2f889b284d5cdbb04b494c03499d777fe3ddf4ee;hb=bc805888417f16602aeb4bfd3f6e33d32ffcae24;hp=67eb611b8223c9381e4e515f208f0894dc7962b1;hpb=1cd1c99be6bbc691878b2a8713f4e75dd41bf206;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c index 67eb611b82..2f889b284d 100644 --- a/gas/config/tc-hppa.c +++ b/gas/config/tc-hppa.c @@ -19,7 +19,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - /* HP PA-RISC support was contributed by the Center for Software Science at the University of Utah. */ @@ -43,7 +42,6 @@ error only one of OBJ_ELF and OBJ_SOM can be defined then we want to use the assembler support for compact line numbers. */ #ifdef OBJ_ELF #include "dwarf2dbg.h" -struct dwarf2_line_info debug_line; /* A "convient" place to put object file dependencies which do not need to be seen outside of tc-hppa.c. */ @@ -232,7 +230,6 @@ struct pa_it /* PA-89 floating point registers are arranged like this: - +--------------+--------------+ | 0 or 16L | 16 or 16R | +--------------+--------------+ @@ -249,23 +246,7 @@ struct pa_it | 14 or 30L | 30 or 30R | +--------------+--------------+ | 15 or 31L | 31 or 31R | - +--------------+--------------+ - - - The following is a version of pa_parse_number that - handles the L/R notation and returns the correct - value to put into the instruction register field. - The correct value to put into the instruction is - encoded in the structure 'pa_11_fp_reg_struct'. */ - -struct pa_11_fp_reg_struct - { - /* The register number. */ - char number_part; - - /* L/R selector. */ - char l_r_select; - }; + +--------------+--------------+ */ /* Additional information needed to build argument relocation stubs. */ struct call_desc @@ -526,9 +507,8 @@ static void pa_proc PARAMS ((int)); static void pa_procend PARAMS ((int)); static void pa_param PARAMS ((int)); static void pa_undefine_label PARAMS ((void)); -static int need_pa11_opcode PARAMS ((struct pa_it *, - struct pa_11_fp_reg_struct *)); -static int pa_parse_number PARAMS ((char **, struct pa_11_fp_reg_struct *)); +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)); @@ -579,6 +559,8 @@ static int pa_parse_ftest_gfx_completer PARAMS ((char **)); #ifdef OBJ_ELF static void hppa_elf_mark_end_of_function PARAMS ((void)); static void pa_build_unwind_subspace PARAMS ((struct call_info *)); +static void pa_vtable_entry PARAMS ((int)); +static void pa_vtable_inherit PARAMS ((int)); #endif /* File and gloally scoped variable declarations. */ @@ -695,6 +677,10 @@ const pseudo_typeS md_pseudo_table[] = {"text", pa_text, 0}, #endif {"version", pa_version, 0}, +#ifdef OBJ_ELF + {"vtable_entry", pa_vtable_entry, 0}, + {"vtable_inherit", pa_vtable_inherit, 0}, +#endif {"word", pa_cons, 4}, {NULL, 0, 0} }; @@ -707,7 +693,7 @@ const pseudo_typeS md_pseudo_table[] = first line of the input file. This is because the compiler outputs #NO_APP at the beginning of its output. - Also note that C style comments will always work. */ + Also note that C style comments will always work. */ const char line_comment_chars[] = "#"; /* This array holds the chars that always start a comment. If the @@ -757,6 +743,15 @@ static int hppa_field_selector; strict syntax checking should be enabled for that instruction. */ static int strict = 0; +/* pa_parse_number returns values in `pa_number'. Mostly + pa_parse_number is used to return a register number, with floating + point registers being numbered from FP_REG_BASE upwards. + The bit specified with FP_REG_RSEL is set if the floating point + register has a `r' suffix. */ +#define FP_REG_BASE 64 +#define FP_REG_RSEL 128 +static int pa_number; + #ifdef OBJ_SOM /* A dummy bfd symbol so that all relocations have symbols of some kind. */ static symbolS *dummy_symbol; @@ -789,206 +784,206 @@ static int print_errors = 1; Almost every control register has a synonym; they are not listed here for brevity. - The table is sorted. Suitable for searching by a binary search. */ + The table is sorted. Suitable for searching by a binary search. */ static const struct pd_reg pre_defined_registers[] = { - {"%arg0", 26}, - {"%arg1", 25}, - {"%arg2", 24}, - {"%arg3", 23}, - {"%cr0", 0}, - {"%cr10", 10}, - {"%cr11", 11}, - {"%cr12", 12}, - {"%cr13", 13}, - {"%cr14", 14}, - {"%cr15", 15}, - {"%cr16", 16}, - {"%cr17", 17}, - {"%cr18", 18}, - {"%cr19", 19}, - {"%cr20", 20}, - {"%cr21", 21}, - {"%cr22", 22}, - {"%cr23", 23}, - {"%cr24", 24}, - {"%cr25", 25}, - {"%cr26", 26}, - {"%cr27", 27}, - {"%cr28", 28}, - {"%cr29", 29}, - {"%cr30", 30}, - {"%cr31", 31}, - {"%cr8", 8}, - {"%cr9", 9}, - {"%dp", 27}, - {"%eiem", 15}, - {"%eirr", 23}, - {"%fr0", 0}, - {"%fr0l", 0}, - {"%fr0r", 0}, - {"%fr1", 1}, - {"%fr10", 10}, - {"%fr10l", 10}, - {"%fr10r", 10}, - {"%fr11", 11}, - {"%fr11l", 11}, - {"%fr11r", 11}, - {"%fr12", 12}, - {"%fr12l", 12}, - {"%fr12r", 12}, - {"%fr13", 13}, - {"%fr13l", 13}, - {"%fr13r", 13}, - {"%fr14", 14}, - {"%fr14l", 14}, - {"%fr14r", 14}, - {"%fr15", 15}, - {"%fr15l", 15}, - {"%fr15r", 15}, - {"%fr16", 16}, - {"%fr16l", 16}, - {"%fr16r", 16}, - {"%fr17", 17}, - {"%fr17l", 17}, - {"%fr17r", 17}, - {"%fr18", 18}, - {"%fr18l", 18}, - {"%fr18r", 18}, - {"%fr19", 19}, - {"%fr19l", 19}, - {"%fr19r", 19}, - {"%fr1l", 1}, - {"%fr1r", 1}, - {"%fr2", 2}, - {"%fr20", 20}, - {"%fr20l", 20}, - {"%fr20r", 20}, - {"%fr21", 21}, - {"%fr21l", 21}, - {"%fr21r", 21}, - {"%fr22", 22}, - {"%fr22l", 22}, - {"%fr22r", 22}, - {"%fr23", 23}, - {"%fr23l", 23}, - {"%fr23r", 23}, - {"%fr24", 24}, - {"%fr24l", 24}, - {"%fr24r", 24}, - {"%fr25", 25}, - {"%fr25l", 25}, - {"%fr25r", 25}, - {"%fr26", 26}, - {"%fr26l", 26}, - {"%fr26r", 26}, - {"%fr27", 27}, - {"%fr27l", 27}, - {"%fr27r", 27}, - {"%fr28", 28}, - {"%fr28l", 28}, - {"%fr28r", 28}, - {"%fr29", 29}, - {"%fr29l", 29}, - {"%fr29r", 29}, - {"%fr2l", 2}, - {"%fr2r", 2}, - {"%fr3", 3}, - {"%fr30", 30}, - {"%fr30l", 30}, - {"%fr30r", 30}, - {"%fr31", 31}, - {"%fr31l", 31}, - {"%fr31r", 31}, - {"%fr3l", 3}, - {"%fr3r", 3}, - {"%fr4", 4}, - {"%fr4l", 4}, - {"%fr4r", 4}, - {"%fr5", 5}, - {"%fr5l", 5}, - {"%fr5r", 5}, - {"%fr6", 6}, - {"%fr6l", 6}, - {"%fr6r", 6}, - {"%fr7", 7}, - {"%fr7l", 7}, - {"%fr7r", 7}, - {"%fr8", 8}, - {"%fr8l", 8}, - {"%fr8r", 8}, - {"%fr9", 9}, - {"%fr9l", 9}, - {"%fr9r", 9}, - {"%hta", 25}, - {"%iir", 19}, - {"%ior", 21}, - {"%ipsw", 22}, - {"%isr", 20}, - {"%itmr", 16}, - {"%iva", 14}, - {"%pcoq", 18}, - {"%pcsq", 17}, - {"%pidr1", 8}, - {"%pidr2", 9}, + {"%arg0", 26}, + {"%arg1", 25}, + {"%arg2", 24}, + {"%arg3", 23}, + {"%cr0", 0}, + {"%cr10", 10}, + {"%cr11", 11}, + {"%cr12", 12}, + {"%cr13", 13}, + {"%cr14", 14}, + {"%cr15", 15}, + {"%cr16", 16}, + {"%cr17", 17}, + {"%cr18", 18}, + {"%cr19", 19}, + {"%cr20", 20}, + {"%cr21", 21}, + {"%cr22", 22}, + {"%cr23", 23}, + {"%cr24", 24}, + {"%cr25", 25}, + {"%cr26", 26}, + {"%cr27", 27}, + {"%cr28", 28}, + {"%cr29", 29}, + {"%cr30", 30}, + {"%cr31", 31}, + {"%cr8", 8}, + {"%cr9", 9}, + {"%dp", 27}, + {"%eiem", 15}, + {"%eirr", 23}, + {"%fr0", 0 + FP_REG_BASE}, + {"%fr0l", 0 + FP_REG_BASE}, + {"%fr0r", 0 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr1", 1 + FP_REG_BASE}, + {"%fr10", 10 + FP_REG_BASE}, + {"%fr10l", 10 + FP_REG_BASE}, + {"%fr10r", 10 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr11", 11 + FP_REG_BASE}, + {"%fr11l", 11 + FP_REG_BASE}, + {"%fr11r", 11 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr12", 12 + FP_REG_BASE}, + {"%fr12l", 12 + FP_REG_BASE}, + {"%fr12r", 12 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr13", 13 + FP_REG_BASE}, + {"%fr13l", 13 + FP_REG_BASE}, + {"%fr13r", 13 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr14", 14 + FP_REG_BASE}, + {"%fr14l", 14 + FP_REG_BASE}, + {"%fr14r", 14 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr15", 15 + FP_REG_BASE}, + {"%fr15l", 15 + FP_REG_BASE}, + {"%fr15r", 15 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr16", 16 + FP_REG_BASE}, + {"%fr16l", 16 + FP_REG_BASE}, + {"%fr16r", 16 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr17", 17 + FP_REG_BASE}, + {"%fr17l", 17 + FP_REG_BASE}, + {"%fr17r", 17 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr18", 18 + FP_REG_BASE}, + {"%fr18l", 18 + FP_REG_BASE}, + {"%fr18r", 18 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr19", 19 + FP_REG_BASE}, + {"%fr19l", 19 + FP_REG_BASE}, + {"%fr19r", 19 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr1l", 1 + FP_REG_BASE}, + {"%fr1r", 1 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr2", 2 + FP_REG_BASE}, + {"%fr20", 20 + FP_REG_BASE}, + {"%fr20l", 20 + FP_REG_BASE}, + {"%fr20r", 20 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr21", 21 + FP_REG_BASE}, + {"%fr21l", 21 + FP_REG_BASE}, + {"%fr21r", 21 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr22", 22 + FP_REG_BASE}, + {"%fr22l", 22 + FP_REG_BASE}, + {"%fr22r", 22 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr23", 23 + FP_REG_BASE}, + {"%fr23l", 23 + FP_REG_BASE}, + {"%fr23r", 23 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr24", 24 + FP_REG_BASE}, + {"%fr24l", 24 + FP_REG_BASE}, + {"%fr24r", 24 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr25", 25 + FP_REG_BASE}, + {"%fr25l", 25 + FP_REG_BASE}, + {"%fr25r", 25 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr26", 26 + FP_REG_BASE}, + {"%fr26l", 26 + FP_REG_BASE}, + {"%fr26r", 26 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr27", 27 + FP_REG_BASE}, + {"%fr27l", 27 + FP_REG_BASE}, + {"%fr27r", 27 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr28", 28 + FP_REG_BASE}, + {"%fr28l", 28 + FP_REG_BASE}, + {"%fr28r", 28 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr29", 29 + FP_REG_BASE}, + {"%fr29l", 29 + FP_REG_BASE}, + {"%fr29r", 29 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr2l", 2 + FP_REG_BASE}, + {"%fr2r", 2 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr3", 3 + FP_REG_BASE}, + {"%fr30", 30 + FP_REG_BASE}, + {"%fr30l", 30 + FP_REG_BASE}, + {"%fr30r", 30 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr31", 31 + FP_REG_BASE}, + {"%fr31l", 31 + FP_REG_BASE}, + {"%fr31r", 31 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr3l", 3 + FP_REG_BASE}, + {"%fr3r", 3 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr4", 4 + FP_REG_BASE}, + {"%fr4l", 4 + FP_REG_BASE}, + {"%fr4r", 4 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr5", 5 + FP_REG_BASE}, + {"%fr5l", 5 + FP_REG_BASE}, + {"%fr5r", 5 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr6", 6 + FP_REG_BASE}, + {"%fr6l", 6 + FP_REG_BASE}, + {"%fr6r", 6 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr7", 7 + FP_REG_BASE}, + {"%fr7l", 7 + FP_REG_BASE}, + {"%fr7r", 7 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr8", 8 + FP_REG_BASE}, + {"%fr8l", 8 + FP_REG_BASE}, + {"%fr8r", 8 + FP_REG_BASE + FP_REG_RSEL}, + {"%fr9", 9 + FP_REG_BASE}, + {"%fr9l", 9 + FP_REG_BASE}, + {"%fr9r", 9 + FP_REG_BASE + FP_REG_RSEL}, + {"%hta", 25}, + {"%iir", 19}, + {"%ior", 21}, + {"%ipsw", 22}, + {"%isr", 20}, + {"%itmr", 16}, + {"%iva", 14}, + {"%pcoq", 18}, + {"%pcsq", 17}, + {"%pidr1", 8}, + {"%pidr2", 9}, {"%pidr3", 12}, {"%pidr4", 13}, - {"%ppda", 24}, - {"%r0", 0}, - {"%r1", 1}, - {"%r10", 10}, - {"%r11", 11}, - {"%r12", 12}, - {"%r13", 13}, - {"%r14", 14}, - {"%r15", 15}, - {"%r16", 16}, - {"%r17", 17}, - {"%r18", 18}, - {"%r19", 19}, - {"%r2", 2}, - {"%r20", 20}, - {"%r21", 21}, - {"%r22", 22}, - {"%r23", 23}, - {"%r24", 24}, - {"%r25", 25}, - {"%r26", 26}, - {"%r27", 27}, - {"%r28", 28}, - {"%r29", 29}, - {"%r3", 3}, - {"%r30", 30}, - {"%r31", 31}, - {"%r4", 4}, - {"%r5", 5}, - {"%r6", 6}, - {"%r7", 7}, - {"%r8", 8}, - {"%r9", 9}, - {"%rctr", 0}, - {"%ret0", 28}, - {"%ret1", 29}, - {"%rp", 2}, - {"%sar", 11}, - {"%sp", 30}, - {"%sr0", 0}, - {"%sr1", 1}, - {"%sr2", 2}, - {"%sr3", 3}, - {"%sr4", 4}, - {"%sr5", 5}, - {"%sr6", 6}, - {"%sr7", 7}, - {"%tr0", 24}, - {"%tr1", 25}, - {"%tr2", 26}, - {"%tr3", 27}, - {"%tr4", 28}, - {"%tr5", 29}, - {"%tr6", 30}, - {"%tr7", 31} + {"%ppda", 24}, + {"%r0", 0}, + {"%r1", 1}, + {"%r10", 10}, + {"%r11", 11}, + {"%r12", 12}, + {"%r13", 13}, + {"%r14", 14}, + {"%r15", 15}, + {"%r16", 16}, + {"%r17", 17}, + {"%r18", 18}, + {"%r19", 19}, + {"%r2", 2}, + {"%r20", 20}, + {"%r21", 21}, + {"%r22", 22}, + {"%r23", 23}, + {"%r24", 24}, + {"%r25", 25}, + {"%r26", 26}, + {"%r27", 27}, + {"%r28", 28}, + {"%r29", 29}, + {"%r3", 3}, + {"%r30", 30}, + {"%r31", 31}, + {"%r4", 4}, + {"%r5", 5}, + {"%r6", 6}, + {"%r7", 7}, + {"%r8", 8}, + {"%r9", 9}, + {"%rctr", 0}, + {"%ret0", 28}, + {"%ret1", 29}, + {"%rp", 2}, + {"%sar", 11}, + {"%sp", 30}, + {"%sr0", 0}, + {"%sr1", 1}, + {"%sr2", 2}, + {"%sr3", 3}, + {"%sr4", 4}, + {"%sr5", 5}, + {"%sr6", 6}, + {"%sr7", 7}, + {"%tr0", 24}, + {"%tr1", 25}, + {"%tr2", 26}, + {"%tr3", 27}, + {"%tr4", 28}, + {"%tr5", 29}, + {"%tr6", 30}, + {"%tr7", 31} }; /* This table is sorted by order of the length of the string. This is @@ -1262,7 +1257,6 @@ pa_undefine_label () } } - /* An HPPA-specific version of fix_new. This is required because the HPPA code needs to keep track of some extra stuff. Each call to fix_new_hppa results in the creation of an instance of an hppa_fix_struct. An @@ -1308,9 +1302,10 @@ fix_new_hppa (frag, where, size, add_symbol, offset, exp, pcrel, /* foo-$global$ is used to access non-automatic storage. $global$ is really just a marker and has served its purpose, so eliminate - it now so as not to confuse write.c. */ + it now so as not to confuse write.c. Ditto for $PIC_pcrel$0. */ if (new_fix->fx_subsy - && !strcmp (S_GET_NAME (new_fix->fx_subsy), "$global$")) + && (strcmp (S_GET_NAME (new_fix->fx_subsy), "$global$") == 0 + || strcmp (S_GET_NAME (new_fix->fx_subsy), "$PIC_pcrel$0") == 0)) new_fix->fx_subsy = NULL; } @@ -1425,7 +1420,7 @@ md_begin () #ifdef OBJ_SOM dummy_symbol = symbol_find_or_make ("L$dummy"); S_SET_SEGMENT (dummy_symbol, text_section); - /* Force the symbol to be converted to a real symbol. */ + /* Force the symbol to be converted to a real symbol. */ (void) symbol_get_bfdsym (dummy_symbol); #endif } @@ -1485,7 +1480,7 @@ md_assemble (str) /* Get somewhere to put the assembled instrution. */ to = frag_more (4); - /* Output the opcode. */ + /* Output the opcode. */ md_number_to_chars (to, the_insn.opcode, 4); /* If necessary output more stuff. */ @@ -1496,20 +1491,7 @@ md_assemble (str) the_insn.format, the_insn.arg_reloc, NULL); #ifdef OBJ_ELF - if (debug_type == DEBUG_DWARF2) - { - bfd_vma addr; - - /* First update the notion of the current source line. */ - dwarf2_where (&debug_line); - - /* We want the offset of the start of this instruction within the - the current frag. */ - addr = frag_now->fr_address + frag_now_fix () - 4; - - /* And record the information. */ - dwarf2_gen_line_info (addr, &debug_line); - } + dwarf2_emit_insn (4); #endif } @@ -1644,10 +1626,9 @@ pa_ip (str) /* Handle a 5 bit register or control register field at 10. */ case 'b': case '^': - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 0)) break; - num = pa_parse_number (&s, 0); + num = pa_number; CHECK_FIELD (num, 31, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 21); @@ -1672,28 +1653,25 @@ pa_ip (str) /* Handle a 5 bit register field at 15. */ case 'x': - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 0)) break; - num = pa_parse_number (&s, 0); + num = pa_number; CHECK_FIELD (num, 31, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 16); /* Handle a 5 bit register field at 31. */ case 't': - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 0)) break; - num = pa_parse_number (&s, 0); + num = pa_number; CHECK_FIELD (num, 31, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 0); /* Handle a 5 bit register field at 10 and 15. */ case 'a': - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 0)) break; - num = pa_parse_number (&s, 0); + num = pa_number; CHECK_FIELD (num, 31, 0, 0); opcode |= num << 16; INSERT_FIELD_AND_CONTINUE (opcode, num, 21); @@ -1760,19 +1738,17 @@ pa_ip (str) /* Handle a 2 bit space identifier at 17. */ case 's': - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 0)) break; - num = pa_parse_number (&s, 0); + num = pa_number; CHECK_FIELD (num, 3, 0, 1); INSERT_FIELD_AND_CONTINUE (opcode, num, 14); /* Handle a 3 bit space identifier at 18. */ case 'S': - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 0)) break; - num = pa_parse_number (&s, 0); + num = pa_number; CHECK_FIELD (num, 7, 0, 1); opcode |= re_assemble_3 (num); continue; @@ -1955,7 +1931,7 @@ pa_ip (str) } INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 10); - /* Handle load ordering completer. */ + /* Handle load ordering completer. */ case 'o': if (strncmp(s, ",o", 2) != 0) break; @@ -2415,7 +2391,7 @@ pa_ip (str) } else { - /* Negated condition requires an opcode change. */ + /* Negated condition requires an opcode change. */ opcode |= (cmpltr & 8) << 24; } INSERT_FIELD_AND_CONTINUE (opcode, cmpltr & 7, 13); @@ -2436,7 +2412,7 @@ pa_ip (str) } else { - /* Negated condition requires an opcode change. */ + /* Negated condition requires an opcode change. */ opcode |= 1 << 27; } } @@ -2589,7 +2565,7 @@ pa_ip (str) } else { - /* Negated condition requires an opcode change. */ + /* Negated condition requires an opcode change. */ opcode |= 1 << 27; } } @@ -2601,11 +2577,11 @@ pa_ip (str) cmpltr = pa_parse_cmpb_64_cmpltr (&s); if (cmpltr >= 0) { - /* Negated condition requires an opcode change. */ + /* Negated condition requires an opcode change. */ opcode |= (cmpltr & 8) << 26; } else - /* Not a 64 bit cond. Give 32 bit a chance. */ + /* Not a 64 bit cond. Give 32 bit a chance. */ break; INSERT_FIELD_AND_CONTINUE (opcode, cmpltr & 7, 13); @@ -2614,7 +2590,7 @@ pa_ip (str) case 'Q': cmpltr = pa_parse_cmpib_64_cmpltr (&s); if (cmpltr < 0) - /* Not a 64 bit cond. Give 32 bit a chance. */ + /* Not a 64 bit cond. Give 32 bit a chance. */ break; INSERT_FIELD_AND_CONTINUE (opcode, cmpltr, 13); @@ -3199,7 +3175,7 @@ pa_ip (str) break; } CHECK_FIELD (num, 8199, -8184, 0); - + opcode |= re_assemble_12 ((num - 8) >> 2); continue; } @@ -3437,8 +3413,6 @@ pa_ip (str) num = pa_get_absolute_expression (&the_insn, &s); if (strict && the_insn.exp.X_op != O_constant) break; - if (the_insn.exp.X_op != O_constant) - break; s = expr_end; CHECK_FIELD (num, 31, 0, strict); INSERT_FIELD_AND_CONTINUE (opcode, num, 21); @@ -3662,49 +3636,43 @@ pa_ip (str) { /* Float target register. */ case 't': - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 3)) break; - num = pa_parse_number (&s, 0); + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; CHECK_FIELD (num, 31, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 0); /* Float target register with L/R selection. */ case 'T': { - struct pa_11_fp_reg_struct result; - - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 1)) break; - pa_parse_number (&s, &result); - CHECK_FIELD (result.number_part, 31, 0, 0); - opcode |= result.number_part; + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; + CHECK_FIELD (num, 31, 0, 0); + opcode |= num; /* 0x30 opcodes are FP arithmetic operation opcodes and need to be turned into 0x38 opcodes. This is not necessary for loads/stores. */ - if (need_pa11_opcode (&the_insn, &result) + if (need_pa11_opcode () && ((opcode & 0xfc000000) == 0x30000000)) opcode |= 1 << 27; - INSERT_FIELD_AND_CONTINUE (opcode, result.l_r_select & 1, 6); + opcode |= (pa_number & FP_REG_RSEL ? 1 << 6 : 0); + continue; } /* Float operand 1. */ case 'a': { - struct pa_11_fp_reg_struct result; - - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 1)) break; - pa_parse_number (&s, &result); - CHECK_FIELD (result.number_part, 31, 0, 0); - opcode |= result.number_part << 21; - if (need_pa11_opcode (&the_insn, &result)) + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; + CHECK_FIELD (num, 31, 0, 0); + opcode |= num << 21; + if (need_pa11_opcode ()) { - opcode |= (result.l_r_select & 1) << 7; + opcode |= (pa_number & FP_REG_RSEL ? 1 << 7 : 0); opcode |= 1 << 27; } continue; @@ -3714,32 +3682,26 @@ pa_ip (str) case 'X': case 'A': { - struct pa_11_fp_reg_struct result; - - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 1)) break; - pa_parse_number (&s, &result); - CHECK_FIELD (result.number_part, 31, 0, 0); - opcode |= result.number_part << 21; - opcode |= (result.l_r_select & 1) << 7; + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; + CHECK_FIELD (num, 31, 0, 0); + opcode |= num << 21; + opcode |= (pa_number & FP_REG_RSEL ? 1 << 7 : 0); continue; } /* Float operand 2. */ case 'b': { - struct pa_11_fp_reg_struct result; - - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 1)) break; - pa_parse_number (&s, &result); - CHECK_FIELD (result.number_part, 31, 0, 0); - opcode |= (result.number_part & 0x1f) << 16; - if (need_pa11_opcode (&the_insn, &result)) + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; + CHECK_FIELD (num, 31, 0, 0); + opcode |= num << 16; + if (need_pa11_opcode ()) { - opcode |= (result.l_r_select & 1) << 12; + opcode |= (pa_number & FP_REG_RSEL ? 1 << 12 : 0); opcode |= 1 << 27; } continue; @@ -3748,174 +3710,149 @@ pa_ip (str) /* Float operand 2 with L/R selection. */ case 'B': { - struct pa_11_fp_reg_struct result; - - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 1)) break; - pa_parse_number (&s, &result); - CHECK_FIELD (result.number_part, 31, 0, 0); - opcode |= (result.number_part & 0x1f) << 16; - opcode |= (result.l_r_select & 1) << 12; + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; + CHECK_FIELD (num, 31, 0, 0); + opcode |= num << 16; + opcode |= (pa_number & FP_REG_RSEL ? 1 << 12 : 0); continue; } /* Float operand 3 for fmpyfadd, fmpynfadd. */ case 'C': { - struct pa_11_fp_reg_struct result; - - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 1)) break; - pa_parse_number (&s, &result); - CHECK_FIELD (result.number_part, 31, 0, 0); - opcode |= (result.number_part & 0x1c) << 11; - opcode |= (result.number_part & 0x3) << 9; - opcode |= (result.l_r_select & 1) << 8; + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; + CHECK_FIELD (num, 31, 0, 0); + opcode |= (num & 0x1c) << 11; + opcode |= (num & 0x03) << 9; + opcode |= (pa_number & FP_REG_RSEL ? 1 << 8 : 0); continue; } /* Float mult operand 1 for fmpyadd, fmpysub */ case 'i': { - struct pa_11_fp_reg_struct result; - - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 1)) break; - pa_parse_number (&s, &result); - CHECK_FIELD (result.number_part, 31, 0, 0); + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; + CHECK_FIELD (num, 31, 0, 0); if (the_insn.fpof1 == SGL) { - if (result.number_part < 16) + if (num < 16) { as_bad (_("Invalid register for single precision fmpyadd or fmpysub")); break; } - - result.number_part &= 0xF; - result.number_part |= (result.l_r_select & 1) << 4; + num &= 0xF; + num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0); } - INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 21); + INSERT_FIELD_AND_CONTINUE (opcode, num, 21); } /* Float mult operand 2 for fmpyadd, fmpysub */ case 'j': { - struct pa_11_fp_reg_struct result; - - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 1)) break; - pa_parse_number (&s, &result); - CHECK_FIELD (result.number_part, 31, 0, 0); + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; + CHECK_FIELD (num, 31, 0, 0); if (the_insn.fpof1 == SGL) { - if (result.number_part < 16) + if (num < 16) { - as_bad (_("Invalid register for single precision fmpyadd or fmpysub")); - break; + as_bad (_("Invalid register for single precision fmpyadd or fmpysub")); + break; } - result.number_part &= 0xF; - result.number_part |= (result.l_r_select & 1) << 4; + num &= 0xF; + num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0); } - INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 16); + INSERT_FIELD_AND_CONTINUE (opcode, num, 16); } /* Float mult target for fmpyadd, fmpysub */ case 'k': { - struct pa_11_fp_reg_struct result; - - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 1)) break; - pa_parse_number (&s, &result); - CHECK_FIELD (result.number_part, 31, 0, 0); + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; + CHECK_FIELD (num, 31, 0, 0); if (the_insn.fpof1 == SGL) { - if (result.number_part < 16) + if (num < 16) { - as_bad (_("Invalid register for single precision fmpyadd or fmpysub")); - break; + as_bad (_("Invalid register for single precision fmpyadd or fmpysub")); + break; } - result.number_part &= 0xF; - result.number_part |= (result.l_r_select & 1) << 4; + num &= 0xF; + num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0); } - INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 0); + INSERT_FIELD_AND_CONTINUE (opcode, num, 0); } /* Float add operand 1 for fmpyadd, fmpysub */ case 'l': { - struct pa_11_fp_reg_struct result; - - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 1)) break; - pa_parse_number (&s, &result); - CHECK_FIELD (result.number_part, 31, 0, 0); + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; + CHECK_FIELD (num, 31, 0, 0); if (the_insn.fpof1 == SGL) { - if (result.number_part < 16) + if (num < 16) { - as_bad (_("Invalid register for single precision fmpyadd or fmpysub")); - break; + as_bad (_("Invalid register for single precision fmpyadd or fmpysub")); + break; } - result.number_part &= 0xF; - result.number_part |= (result.l_r_select & 1) << 4; + num &= 0xF; + num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0); } - INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 6); + INSERT_FIELD_AND_CONTINUE (opcode, num, 6); } /* Float add target for fmpyadd, fmpysub */ case 'm': { - struct pa_11_fp_reg_struct result; - - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 1)) break; - pa_parse_number (&s, &result); - CHECK_FIELD (result.number_part, 31, 0, 0); + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; + CHECK_FIELD (num, 31, 0, 0); if (the_insn.fpof1 == SGL) { - if (result.number_part < 16) + if (num < 16) { - as_bad (_("Invalid register for single precision fmpyadd or fmpysub")); - break; + as_bad (_("Invalid register for single precision fmpyadd or fmpysub")); + break; } - result.number_part &= 0xF; - result.number_part |= (result.l_r_select & 1) << 4; + num &= 0xF; + num |= (pa_number & FP_REG_RSEL ? 1 << 4 : 0); } - INSERT_FIELD_AND_CONTINUE (opcode, result.number_part, 11); + INSERT_FIELD_AND_CONTINUE (opcode, num, 11); } /* Handle L/R register halves like 'x'. */ case 'E': case 'e': { - struct pa_11_fp_reg_struct result; - - if (strict && *s != '%') + if (!pa_parse_number (&s, 1)) break; - pa_parse_number (&s, &result); - CHECK_FIELD (result.number_part, 31, 0, 0); - opcode |= (result.number_part & 0x1f) << 16; - if (need_pa11_opcode (&the_insn, &result)) + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; + CHECK_FIELD (num, 31, 0, 0); + opcode |= num << 16; + if (need_pa11_opcode ()) { - opcode |= (result.l_r_select & 1) << 1; + opcode |= (pa_number & FP_REG_RSEL ? 1 << 1 : 0); } continue; } /* Float target register (PA 2.0 wide). */ case 'x': - /* This should be more strict. Small steps. */ - if (strict && *s != '%') + if (!pa_parse_number (&s, 3)) break; - num = pa_parse_number (&s, 0); + num = (pa_number & ~FP_REG_RSEL) - FP_REG_BASE; CHECK_FIELD (num, 31, 0, 0); INSERT_FIELD_AND_CONTINUE (opcode, num, 16); @@ -4060,7 +3997,10 @@ tc_gen_reloc (section, fixp) symbol_get_bfdsym (fixp->fx_addsy)); if (codes == NULL) - abort (); + { + as_bad (_("Cannot handle fixup at %s:%d"), fixp->fx_file, fixp->fx_line); + abort (); + } for (n_relocs = 0; codes[n_relocs]; n_relocs++) ; @@ -4099,9 +4039,8 @@ tc_gen_reloc (section, fixp) case R_PARISC_PLABEL14R: /* For plabel relocations, the addend of the relocation should be either 0 (no static link) or 2 - (static link required). - - FIXME: We always assume no static link! + (static link required). This adjustment is done in + bfd/elf32-hppa.c:elf32_hppa_relocate_section. We also slam a zero addend into the DLT relative relocs; it doesn't make a lot of sense to use any addend since @@ -4115,52 +4054,10 @@ tc_gen_reloc (section, fixp) case R_PARISC_PCREL17C: case R_PARISC_DIR17R: case R_PARISC_DIR17F: - { - char *buf = fixp->fx_where + fixp->fx_frag->fr_literal; - int insn = bfd_get_32 (stdoutput, buf); - -#ifdef ELF_ARG_RELOC_INSN - /* Store the arg reloc in the instruction. */ - insn = ((insn & ~ 0x1ff8) - | ((hppa_fixp->fx_arg_reloc << 3) & 0x1ff8)); - bfd_put_32 (stdoutput, insn, buf); - reloc->addend = fixp->fx_offset; -#else - /* The high 22 bits of the constant are stored in the - reloc. The remaining 10 bits can be retrieved from the - instruction. */ - insn = (insn & ~ 0x7f8) | ((fixp->fx_offset & 0x3fc) << 1); - bfd_put_32 (stdoutput, insn, buf); - reloc->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc, - fixp->fx_offset >> 10); -#endif - } - break; - case R_PARISC_PCREL21L: case R_PARISC_DIR21L: - { - char *buf = fixp->fx_where + fixp->fx_frag->fr_literal; - int insn = bfd_get_32 (stdoutput, buf); - -#ifdef ELF_ARG_RELOC_INSN - /* Store the arg reloc in the instruction. */ - insn = ((insn & ~ 0xff9) - | ((hppa_fixp->fx_arg_reloc >> 9) & 1) - | ((hppa_fixp->fx_arg_reloc << 3) & 0xff8)); - bfd_put_32 (stdoutput, insn, buf); - reloc->addend = fixp->fx_offset; -#else - /* In this case, the instruction stores the high bits, so - the reloc stores the low 22 bits. */ - insn = ((insn & ~ 0xff9) - | ((fixp->fx_offset >> 31) & 1) - | ((fixp->fx_offset >> 19) & 0xff8)); - bfd_put_32 (stdoutput, insn, buf); - reloc->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc, - fixp->fx_offset); -#endif - } + reloc->addend = HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc, + fixp->fx_offset); break; #endif @@ -4315,7 +4212,7 @@ md_convert_frag (abfd, sec, fragP) } } -/* Round up a section size to the appropriate boundary. */ +/* Round up a section size to the appropriate boundary. */ valueT md_section_align (segment, size) @@ -4345,15 +4242,26 @@ md_estimate_size_before_relax (fragP, segment) } #ifdef OBJ_ELF +# ifdef WARN_COMMENTS +const char *md_shortopts = "Vc"; +# else const char *md_shortopts = "V"; +# endif #else +# ifdef WARN_COMMENTS +const char *md_shortopts = "c"; +# else const char *md_shortopts = ""; +# endif #endif struct option md_longopts[] = { +#ifdef WARN_COMMENTS + {"warn-comment", no_argument, NULL, 'c'}, +#endif {NULL, no_argument, NULL, 0} }; -size_t md_longopts_size = sizeof(md_longopts); +size_t md_longopts_size = sizeof (md_longopts); int md_parse_option (c, arg) @@ -4369,6 +4277,11 @@ md_parse_option (c, arg) case 'V': print_version_id (); break; +#endif +#ifdef WARN_COMMENTS + case 'c': + warn_comment = 1; + break; #endif } @@ -4379,6 +4292,14 @@ void md_show_usage (stream) FILE *stream ATTRIBUTE_UNUSED; { +#ifdef OBJ_ELF + fprintf (stream, _("\ + -Q ignored\n")); +#endif +#ifdef WARN_COMMENTS + fprintf (stream, _("\ + -c print a warning if a comment is found\n")); +#endif } /* We have no need to default values of symbols. */ @@ -4390,9 +4311,11 @@ md_undefined_symbol (name) return 0; } -#if defined (SOM) || defined (ELF_ARG_RELOC) +#if defined (OBJ_SOM) || defined (ELF_ARG_RELOC) +#define nonzero_dibits(x) \ + ((x) | (((x) & 0x55555555) << 1) | (((x) & 0xAAAAAAAA) >> 1)) #define arg_reloc_stub_needed(CALLER, CALLEE) \ - ((CALLEE) && (CALLER) && ((CALLEE) != (CALLER))) + (((CALLER) ^ (CALLEE)) & nonzero_dibits (CALLER) & nonzero_dibits (CALLEE)) #else #define arg_reloc_stub_needed(CALLER, CALLEE) 0 #endif @@ -4404,12 +4327,11 @@ md_apply_fix (fixP, valp) fixS *fixP; valueT *valp; { - char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; + unsigned char *buf; struct hppa_fix_struct *hppa_fixP; offsetT new_val; - int insn, val; + int insn, val, fmt; - hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data; /* SOM uses R_HPPA_ENTRY and R_HPPA_EXIT relocations which can never be "applied" (they are just markers). Likewise for R_HPPA_BEGIN_BRTAB and R_HPPA_END_BRTAB. */ @@ -4430,178 +4352,191 @@ md_apply_fix (fixP, valp) return 1; } #endif +#ifdef OBJ_ELF + if (fixP->fx_r_type == (int) R_PARISC_GNU_VTENTRY + || fixP->fx_r_type == (int) R_PARISC_GNU_VTINHERIT) + return 1; +#endif - insn = bfd_get_32 (stdoutput, (unsigned char *) buf); /* There should have been an HPPA specific fixup associated with the GAS fixup. */ - if (hppa_fixP) + hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data; + if (hppa_fixP == NULL) { - int fmt = bfd_hppa_insn2fmt (stdoutput, insn); - - /* If there is a symbol associated with this fixup, then it's something - which will need a SOM relocation (except for some PC-relative relocs). - In such cases we should treat the "val" or "addend" as zero since it - will be added in as needed from fx_offset in tc_gen_reloc. */ - if ((fixP->fx_addsy != NULL - || fixP->fx_r_type == (int) R_HPPA_NONE) + printf (_("no hppa_fixup entry for fixup type 0x%x at %s:%d"), + fixP->fx_r_type, fixP->fx_file, fixP->fx_line); + return 0; + } + + buf = fixP->fx_frag->fr_literal + fixP->fx_where; + insn = bfd_get_32 (stdoutput, buf); + fmt = bfd_hppa_insn2fmt (stdoutput, insn); + + /* If there is a symbol associated with this fixup, then it's something + which will need a SOM relocation (except for some PC-relative relocs). + In such cases we should treat the "val" or "addend" as zero since it + will be added in as needed from fx_offset in tc_gen_reloc. */ + if ((fixP->fx_addsy != NULL + || fixP->fx_r_type == (int) R_HPPA_NONE) #ifdef OBJ_SOM - && fmt != 32 + && fmt != 32 #endif - ) - new_val = ((fmt == 12 || fmt == 17 || fmt == 22) ? 8 : 0); + ) + new_val = ((fmt == 12 || fmt == 17 || fmt == 22) ? 8 : 0); #ifdef OBJ_SOM - /* These field selectors imply that we do not want an addend. */ - else if (hppa_fixP->fx_r_field == e_psel - || hppa_fixP->fx_r_field == e_rpsel - || hppa_fixP->fx_r_field == e_lpsel - || hppa_fixP->fx_r_field == e_tsel - || hppa_fixP->fx_r_field == e_rtsel - || hppa_fixP->fx_r_field == e_ltsel) - new_val = ((fmt == 12 || fmt == 17 || fmt == 22) ? 8 : 0); - /* This is truely disgusting. The machine independent code blindly - adds in the value of the symbol being relocated against. Damn! */ - else if (fmt == 32 - && fixP->fx_addsy != NULL - && S_GET_SEGMENT (fixP->fx_addsy) != bfd_com_section_ptr) - new_val = hppa_field_adjust (*valp - S_GET_VALUE (fixP->fx_addsy), - 0, hppa_fixP->fx_r_field); + /* These field selectors imply that we do not want an addend. */ + else if (hppa_fixP->fx_r_field == e_psel + || hppa_fixP->fx_r_field == e_rpsel + || hppa_fixP->fx_r_field == e_lpsel + || hppa_fixP->fx_r_field == e_tsel + || hppa_fixP->fx_r_field == e_rtsel + || hppa_fixP->fx_r_field == e_ltsel) + new_val = ((fmt == 12 || fmt == 17 || fmt == 22) ? 8 : 0); + /* This is truly disgusting. The machine independent code blindly + adds in the value of the symbol being relocated against. Damn! */ + else if (fmt == 32 + && fixP->fx_addsy != NULL + && S_GET_SEGMENT (fixP->fx_addsy) != bfd_com_section_ptr) + new_val = hppa_field_adjust (*valp - S_GET_VALUE (fixP->fx_addsy), + 0, hppa_fixP->fx_r_field); #endif - else - new_val = hppa_field_adjust (*valp, 0, hppa_fixP->fx_r_field); - - /* Handle pc-relative exceptions from above. */ - if ((fmt == 12 || fmt == 17 || fmt == 22) - && fixP->fx_addsy - && fixP->fx_pcrel - && !arg_reloc_stub_needed (symbol_arg_reloc_info (fixP->fx_addsy), - hppa_fixP->fx_arg_reloc) - && ((*valp + 8192) < 16384 - || (fmt == 17 && (*valp + 262144) < 524288) - || (fmt == 22 && (*valp + 8388608) < 16777216)) - && S_GET_SEGMENT (fixP->fx_addsy) == hppa_fixP->segment - && !(fixP->fx_subsy - && S_GET_SEGMENT (fixP->fx_subsy) != hppa_fixP->segment)) - { - new_val = hppa_field_adjust (*valp, 0, hppa_fixP->fx_r_field); - } - - switch (fmt) - { - case 10: - CHECK_FIELD (new_val, 8191, -8192, 0); - val = new_val; + else + new_val = hppa_field_adjust (*valp, 0, hppa_fixP->fx_r_field); + + /* Handle pc-relative exceptions from above. */ + if ((fmt == 12 || fmt == 17 || fmt == 22) + && fixP->fx_addsy + && fixP->fx_pcrel + && !arg_reloc_stub_needed (symbol_arg_reloc_info (fixP->fx_addsy), + hppa_fixP->fx_arg_reloc) +#ifdef OBJ_ELF + && (*valp - 8 + 8192 < 16384 + || (fmt == 17 && *valp - 8 + 262144 < 524288) + || (fmt == 22 && *valp - 8 + 8388608 < 16777216)) +#endif +#ifdef OBJ_SOM + && (*valp - 8 + 262144 < 524288 + || (fmt == 22 && *valp - 8 + 8388608 < 16777216)) +#endif + && !S_IS_EXTERNAL (fixP->fx_addsy) + && !S_IS_WEAK (fixP->fx_addsy) + && S_GET_SEGMENT (fixP->fx_addsy) == hppa_fixP->segment + && !(fixP->fx_subsy + && S_GET_SEGMENT (fixP->fx_subsy) != hppa_fixP->segment)) + { + new_val = hppa_field_adjust (*valp, 0, hppa_fixP->fx_r_field); + } - insn = (insn & ~ 0x3ff1) | (((val & 0x1ff8) << 1) - | ((val & 0x2000) >> 13)); - break; - case -11: - CHECK_FIELD (new_val, 8191, -8192, 0); - val = new_val; + switch (fmt) + { + case 10: + CHECK_FIELD (new_val, 8191, -8192, 0); + val = new_val; - insn = (insn & ~ 0x3ff9) | (((val & 0x1ffc) << 1) - | ((val & 0x2000) >> 13)); - break; - /* Handle all opcodes with the 'j' operand type. */ - case 14: - CHECK_FIELD (new_val, 8191, -8192, 0); - val = new_val; + insn = (insn & ~ 0x3ff1) | (((val & 0x1ff8) << 1) + | ((val & 0x2000) >> 13)); + break; + case -11: + CHECK_FIELD (new_val, 8191, -8192, 0); + val = new_val; - insn = ((insn & ~ 0x3fff) | low_sign_unext (val, 14)); - break; + insn = (insn & ~ 0x3ff9) | (((val & 0x1ffc) << 1) + | ((val & 0x2000) >> 13)); + break; + /* Handle all opcodes with the 'j' operand type. */ + case 14: + CHECK_FIELD (new_val, 8191, -8192, 0); + val = new_val; - /* Handle all opcodes with the 'k' operand type. */ - case 21: - CHECK_FIELD (new_val, 1048575, -1048576, 0); - val = new_val; + insn = ((insn & ~ 0x3fff) | low_sign_unext (val, 14)); + break; - insn = (insn & ~ 0x1fffff) | re_assemble_21 (val); - break; + /* Handle all opcodes with the 'k' operand type. */ + case 21: + CHECK_FIELD (new_val, 1048575, -1048576, 0); + val = new_val; - /* Handle all the opcodes with the 'i' operand type. */ - case 11: - CHECK_FIELD (new_val, 1023, -1023, 0); - val = new_val; + insn = (insn & ~ 0x1fffff) | re_assemble_21 (val); + break; - insn = (insn & ~ 0x7ff) | low_sign_unext (val, 11); - break; + /* Handle all the opcodes with the 'i' operand type. */ + case 11: + CHECK_FIELD (new_val, 1023, -1023, 0); + val = new_val; - /* Handle all the opcodes with the 'w' operand type. */ - case 12: - CHECK_FIELD (new_val, 8199, -8184, 0); - val = new_val; + insn = (insn & ~ 0x7ff) | low_sign_unext (val, 11); + break; - insn = (insn & ~ 0x1ffd) | re_assemble_12 ((val - 8) >> 2); - break; + /* Handle all the opcodes with the 'w' operand type. */ + case 12: + CHECK_FIELD (new_val - 8, 8191, -8192, 0); + val = new_val - 8; - /* Handle some of the opcodes with the 'W' operand type. */ - case 17: - { - offsetT distance = *valp; + insn = (insn & ~ 0x1ffd) | re_assemble_12 (val >> 2); + break; - /* If this is an absolute branch (ie no link) with an out of - range target, then we want to complain. */ - if (fixP->fx_r_type == (int) R_HPPA_PCREL_CALL - && (insn & 0xffe00000) == 0xe8000000) - CHECK_FIELD (distance, 262143, -262144, 0); + /* Handle some of the opcodes with the 'W' operand type. */ + case 17: + { + offsetT distance = *valp; - CHECK_FIELD (new_val, 262143, -262144, 0); - val = new_val; + /* If this is an absolute branch (ie no link) with an out of + range target, then we want to complain. */ + if (fixP->fx_r_type == (int) R_HPPA_PCREL_CALL + && (insn & 0xffe00000) == 0xe8000000) + CHECK_FIELD (distance - 8, 262143, -262144, 0); - insn = (insn & ~ 0x1f1ffd) | re_assemble_17 ((val - 8) >> 2); - break; - } + CHECK_FIELD (new_val - 8, 262143, -262144, 0); + val = new_val - 8; - case 22: - { - offsetT distance = *valp; + insn = (insn & ~ 0x1f1ffd) | re_assemble_17 (val >> 2); + break; + } - /* If this is an absolute branch (ie no link) with an out of - range target, then we want to complain. */ - if (fixP->fx_r_type == (int) R_HPPA_PCREL_CALL - && (insn & 0xffe00000) == 0xe8000000) - CHECK_FIELD (distance, 8388607, -8388608, 0); + case 22: + { + offsetT distance = *valp; - CHECK_FIELD (new_val, 8388607, -8388608, 0); - val = new_val; + /* If this is an absolute branch (ie no link) with an out of + range target, then we want to complain. */ + if (fixP->fx_r_type == (int) R_HPPA_PCREL_CALL + && (insn & 0xffe00000) == 0xe8000000) + CHECK_FIELD (distance - 8, 8388607, -8388608, 0); - insn = (insn & ~ 0x3ff1ffd) | re_assemble_22 ((val - 8) >> 2); - break; - } + CHECK_FIELD (new_val - 8, 8388607, -8388608, 0); + val = new_val - 8; - case -10: - val = new_val; - insn = (insn & ~ 0xfff1) | re_assemble_16 (val & -8); - break; + insn = (insn & ~ 0x3ff1ffd) | re_assemble_22 (val >> 2); + break; + } - case -16: - val = new_val; - insn = (insn & ~ 0xfff9) | re_assemble_16 (val & -4); - break; + case -10: + val = new_val; + insn = (insn & ~ 0xfff1) | re_assemble_16 (val & -8); + break; - case 16: - val = new_val; - insn = (insn & ~ 0xffff) | re_assemble_16 (val); - break; + case -16: + val = new_val; + insn = (insn & ~ 0xfff9) | re_assemble_16 (val & -4); + break; - case 32: - insn = new_val; - break; + case 16: + val = new_val; + insn = (insn & ~ 0xffff) | re_assemble_16 (val); + break; - default: - as_bad (_("Unknown relocation encountered in md_apply_fix.")); - return 0; - } + case 32: + insn = new_val; + break; - /* Insert the relocation. */ - bfd_put_32 (stdoutput, insn, (unsigned char *) buf); - return 1; - } - else - { - printf (_("no hppa_fixup entry for this fixup (fixP = 0x%x, type = 0x%x)\n"), - (unsigned int) fixP, fixP->fx_r_type); + default: + as_bad (_("Unknown relocation encountered in md_apply_fix.")); return 0; } + + /* Insert the relocation. */ + bfd_put_32 (stdoutput, insn, buf); + return 1; } /* Exactly what point is a PC-relative offset relative TO? @@ -4629,19 +4564,21 @@ is_end_of_statement () the most common will be a hex or decimal constant, but it could be a pre-defined register (Yuk!), or an absolute symbol. - Return a number or -1 for failure. + Return 1 on success or 0 on failure. If STRICT, then a missing + register prefix will cause a failure. The number itself is + returned in `pa_number'. - When parsing PA-89 FP register numbers RESULT will be - the address of a structure to return information about - L/R half of FP registers, store results there as appropriate. + IS_FLOAT indicates that a PA-89 FP register number should be + parsed; A `l' or `r' suffix is checked for if but 2 of IS_FLOAT is + not set. pa_parse_number can not handle negative constants and will fail horribly if it is passed such a constant. */ static int -pa_parse_number (s, result) +pa_parse_number (s, is_float) char **s; - struct pa_11_fp_reg_struct *result; + int is_float; { int num; char *name; @@ -4649,23 +4586,18 @@ pa_parse_number (s, result) symbolS *sym; int status; char *p = *s; + boolean have_prefix; /* Skip whitespace before the number. */ while (*p == ' ' || *p == '\t') p = p + 1; - /* Store info in RESULT if requested by caller. */ - if (result) - { - result->number_part = -1; - result->l_r_select = -1; - } - num = -1; - - if (isdigit (*p)) + pa_number = -1; + have_prefix = 0; + num = 0; + if (!strict && isdigit (*p)) { /* Looks like a number. */ - num = 0; if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X')) { @@ -4693,35 +4625,36 @@ pa_parse_number (s, result) } } - /* Store info in RESULT if requested by the caller. */ - if (result) - { - result->number_part = num; + pa_number = num; - if (IS_R_SELECT (p)) - { - result->l_r_select = 1; - ++p; - } - else if (IS_L_SELECT (p)) + /* Check for a `l' or `r' suffix. */ + if (is_float) + { + pa_number += FP_REG_BASE; + if (! (is_float & 2)) { - result->l_r_select = 0; - ++p; + if (IS_R_SELECT (p)) + { + pa_number += FP_REG_RSEL; + ++p; + } + else if (IS_L_SELECT (p)) + { + ++p; + } } - else - result->l_r_select = 0; } } else if (*p == '%') { /* The number might be a predefined register. */ - num = 0; + have_prefix = 1; name = p; p++; c = *p; /* Tege hack: Special case for general registers as the general code makes a binary search with case translation, and is VERY - slow. */ + slow. */ if (c == 'r') { p++; @@ -4771,23 +4704,12 @@ pa_parse_number (s, result) *p = c; } - /* Store info in RESULT if requested by caller. */ - if (result) - { - result->number_part = num; - if (IS_R_SELECT (p - 1)) - result->l_r_select = 1; - else if (IS_L_SELECT (p - 1)) - result->l_r_select = 0; - else - result->l_r_select = 0; - } + pa_number = num; } else { /* And finally, it could be a symbol in the absolute section which - is effectively a constant. */ - num = 0; + is effectively a constant, or a register alias symbol. */ name = p; c = *p; while (is_part_of_name (c)) @@ -4798,16 +4720,23 @@ pa_parse_number (s, result) *p = 0; if ((sym = symbol_find (name)) != NULL) { - if (S_GET_SEGMENT (sym) == &bfd_abs_section) + if (S_GET_SEGMENT (sym) == reg_section) + { + num = S_GET_VALUE (sym); + /* Well, we don't really have one, but we do have a + register, so... */ + have_prefix = true; + } + else if (S_GET_SEGMENT (sym) == &bfd_abs_section) num = S_GET_VALUE (sym); - else + else if (!strict) { if (print_errors) as_bad (_("Non-absolute symbol: '%s'."), name); num = -1; } } - else + else if (!strict) { /* There is where we'd come for an undefined symbol or for an empty string. For an empty string we @@ -4824,24 +4753,18 @@ pa_parse_number (s, result) } *p = c; - /* Store info in RESULT if requested by caller. */ - if (result) - { - result->number_part = num; - if (IS_R_SELECT (p - 1)) - result->l_r_select = 1; - else if (IS_L_SELECT (p - 1)) - result->l_r_select = 0; - else - result->l_r_select = 0; - } + pa_number = num; } - *s = p; - return num; + if (!strict || have_prefix) + { + *s = p; + return 1; + } + return 0; } -#define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct pd_reg)) +#define REG_NAME_CNT (sizeof (pre_defined_registers) / sizeof (struct pd_reg)) /* Given NAME, find the register number associated with that name, return the integer value associated with the given name or -1 on failure. */ @@ -4872,16 +4795,14 @@ reg_name_search (name) return -1; } - /* Return nonzero if the given INSN and L/R information will require a new PA-1.1 opcode. */ static int -need_pa11_opcode (insn, result) - struct pa_it *insn; - struct pa_11_fp_reg_struct *result; +need_pa11_opcode () { - if (result->l_r_select == 1 && !(insn->fpof1 == DBL && insn->fpof2 == DBL)) + if ((pa_number & FP_REG_RSEL) != 0 + && !(the_insn.fpof1 == DBL && the_insn.fpof2 == DBL)) { /* If this instruction is specific to a particular architecture, then set a new architecture. */ @@ -5177,7 +5098,7 @@ get_expression (str) return 0; } -/* Mark (via expr_end) the end of an absolute expression. FIXME. */ +/* Mark (via expr_end) the end of an absolute expression. FIXME. */ static int pa_get_absolute_expression (insn, strp) struct pa_it *insn; @@ -5193,7 +5114,7 @@ pa_get_absolute_expression (insn, strp) The PA assembly syntax is ambigious 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 5? + r5, or is that 4 MOD r5? If we get a modulo expresion When looking for an absolute, we try again cutting off the input string at the first whitespace character. */ @@ -5359,7 +5280,6 @@ pa_parse_nonneg_cmpsub_cmpltr (s, isbranch) c = **s; **s = 0x00; - if (strcmp (name, "=") == 0) { cmpltr = 1; @@ -5406,7 +5326,6 @@ pa_parse_nonneg_cmpsub_cmpltr (s, isbranch) if (nullify) *s = save_s; - return cmpltr; } @@ -5437,7 +5356,6 @@ pa_parse_neg_cmpsub_cmpltr (s, isbranch) c = **s; **s = 0x00; - if (strcasecmp (name, "tr") == 0) { cmpltr = 0; @@ -5488,11 +5406,9 @@ pa_parse_neg_cmpsub_cmpltr (s, isbranch) if (nullify) *s = save_s; - return cmpltr; } - /* Parse a 64 bit compare and branch completer returning the number (for encoding in instrutions) of the given completer. @@ -5587,7 +5503,6 @@ pa_parse_cmpb_64_cmpltr (s) **s = c; } - return cmpltr; } @@ -5650,7 +5565,6 @@ pa_parse_cmpib_64_cmpltr (s) **s = c; } - return cmpltr; } @@ -5911,6 +5825,7 @@ pa_parse_addb_64_cmpltr (s) alignment of the subspace if necessary. */ static void pa_align (bytes) + int bytes; { /* We must have a valid space and subspace. */ pa_check_current_space_and_subspace (); @@ -6136,7 +6051,6 @@ pa_build_unwind_subspace (call_info) subseg_set (seg, 0); - /* Get some space to hold relocation information for the unwind descriptor. */ p = frag_more (4); @@ -6164,7 +6078,7 @@ pa_build_unwind_subspace (call_info) (expressionS *) NULL, 0, reloc, e_fsel, 32, 0, NULL); - /* Dump it. */ + /* Dump it. */ unwind = (char *) &call_info->ci_unwind; for (i = 8; i < sizeof (struct unwind_table); i++) { @@ -6472,6 +6386,27 @@ pa_entry (unused) #endif } +/* Silly nonsense for pa_equ. The only half-sensible use for this is + being able to subtract two register symbols that specify a range of + registers, to get the size of the range. */ +static int fudge_reg_expressions; + +int +hppa_force_reg_syms_absolute (resultP, op, rightP) + expressionS *resultP; + operatorT op ATTRIBUTE_UNUSED; + expressionS *rightP; +{ + if (fudge_reg_expressions + && rightP->X_op == O_register + && resultP->X_op == O_register) + { + rightP->X_op = O_constant; + resultP->X_op = O_constant; + } + return 0; /* Continue normal expr handling. */ +} + /* Handle a .EQU pseudo-op. */ static void @@ -6485,10 +6420,32 @@ pa_equ (reg) { symbol = label_symbol->lss_label; if (reg) - S_SET_VALUE (symbol, pa_parse_number (&input_line_pointer, 0)); + { + strict = 1; + if (!pa_parse_number (&input_line_pointer, 0)) + as_bad (_(".REG expression must be a register")); + S_SET_VALUE (symbol, pa_number); + S_SET_SEGMENT (symbol, reg_section); + } else - S_SET_VALUE (symbol, (unsigned int) get_absolute_expression ()); - S_SET_SEGMENT (symbol, bfd_abs_section_ptr); + { + expressionS exp; + segT seg; + + fudge_reg_expressions = 1; + seg = expression (&exp); + fudge_reg_expressions = 0; + if (exp.X_op != O_constant + && exp.X_op != O_register) + { + if (exp.X_op != O_absent) + as_bad (_("bad or irreducible absolute expression; zero assumed")); + exp.X_add_number = 0; + seg = absolute_section; + } + S_SET_VALUE (symbol, (unsigned int) exp.X_add_number); + S_SET_SEGMENT (symbol, seg); + } } else { @@ -6591,7 +6548,7 @@ pa_export (unused) else { /* OK. Set the external bits and process argument relocations. - For the HP, weak and global are not mutually exclusive. + For the HP, weak and global are not mutually exclusive. S_SET_EXTERNAL will not set BSF_GLOBAL if WEAK is set. Call S_SET_EXTERNAL to get the other processing. Manually set BSF_GLOBAL when we get back. */ @@ -6619,12 +6576,13 @@ pa_type_args (symbolP, is_export) char *name, c, *p; unsigned int temp, arg_reloc; pa_symbol_type type = SYMBOL_TYPE_UNKNOWN; + asymbol *bfdsym = symbol_get_bfdsym (symbolP); if (strncasecmp (input_line_pointer, "absolute", 8) == 0) { input_line_pointer += 8; - symbol_get_bfdsym (symbolP)->flags &= ~BSF_FUNCTION; + bfdsym->flags &= ~BSF_FUNCTION; S_SET_SEGMENT (symbolP, bfd_abs_section_ptr); type = SYMBOL_TYPE_ABSOLUTE; } @@ -6643,50 +6601,58 @@ pa_type_args (symbolP, is_export) as_tsktsk (_("Using ENTRY rather than CODE in export directive for %s"), S_GET_NAME (symbolP)); - symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION; + bfdsym->flags |= BSF_FUNCTION; type = SYMBOL_TYPE_ENTRY; } else { - symbol_get_bfdsym (symbolP)->flags &= ~BSF_FUNCTION; + bfdsym->flags &= ~BSF_FUNCTION; type = SYMBOL_TYPE_CODE; } } else if (strncasecmp (input_line_pointer, "data", 4) == 0) { input_line_pointer += 4; - symbol_get_bfdsym (symbolP)->flags &= ~BSF_FUNCTION; - symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT; + bfdsym->flags &= ~BSF_FUNCTION; + bfdsym->flags |= BSF_OBJECT; type = SYMBOL_TYPE_DATA; } else if ((strncasecmp (input_line_pointer, "entry", 5) == 0)) { input_line_pointer += 5; - symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION; + bfdsym->flags |= BSF_FUNCTION; type = SYMBOL_TYPE_ENTRY; } else if (strncasecmp (input_line_pointer, "millicode", 9) == 0) { input_line_pointer += 9; - symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION; + bfdsym->flags |= BSF_FUNCTION; +#ifdef OBJ_ELF + { + elf_symbol_type *elfsym = (elf_symbol_type *) bfdsym; + elfsym->internal_elf_sym.st_info = + ELF_ST_INFO (ELF_ST_BIND (elfsym->internal_elf_sym.st_info), + STT_PARISC_MILLI); + } +#endif type = SYMBOL_TYPE_MILLICODE; } else if (strncasecmp (input_line_pointer, "plabel", 6) == 0) { input_line_pointer += 6; - symbol_get_bfdsym (symbolP)->flags &= ~BSF_FUNCTION; + bfdsym->flags &= ~BSF_FUNCTION; type = SYMBOL_TYPE_PLABEL; } else if (strncasecmp (input_line_pointer, "pri_prog", 8) == 0) { input_line_pointer += 8; - symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION; + bfdsym->flags |= BSF_FUNCTION; type = SYMBOL_TYPE_PRI_PROG; } else if (strncasecmp (input_line_pointer, "sec_prog", 8) == 0) { input_line_pointer += 8; - symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION; + bfdsym->flags |= BSF_FUNCTION; type = SYMBOL_TYPE_SEC_PROG; } @@ -6694,7 +6660,7 @@ pa_type_args (symbolP, is_export) than BFD understands. This is how we get this information to the SOM BFD backend. */ #ifdef obj_set_symbol_type - obj_set_symbol_type (symbol_get_bfdsym (symbolP), (int) type); + obj_set_symbol_type (bfdsym, (int) type); #endif /* Now that the type of the exported symbol has been handled, @@ -6715,7 +6681,7 @@ pa_type_args (symbolP, is_export) name = input_line_pointer; c = get_symbol_end (); arg_reloc = pa_align_arg_reloc (temp, pa_build_arg_reloc (name)); -#if defined (SOM) || defined (ELF_ARG_RELOC) +#if defined (OBJ_SOM) || defined (ELF_ARG_RELOC) symbol_arg_reloc_info (symbolP) |= arg_reloc; #endif *input_line_pointer = c; @@ -6729,7 +6695,7 @@ pa_type_args (symbolP, is_export) name = input_line_pointer; c = get_symbol_end (); arg_reloc = pa_build_arg_reloc (name); -#if defined (SOM) || defined (ELF_ARG_RELOC) +#if defined (OBJ_SOM) || defined (ELF_ARG_RELOC) symbol_arg_reloc_info (symbolP) |= arg_reloc; #endif *input_line_pointer = c; @@ -6742,8 +6708,7 @@ pa_type_args (symbolP, is_export) input_line_pointer++; temp = atoi (input_line_pointer); #ifdef OBJ_SOM - ((obj_symbol_type *) symbol_get_bfdsym (symbolP)) - ->tc_data.ap.hppa_priv_level = temp; + ((obj_symbol_type *) bfdsym)->tc_data.ap.hppa_priv_level = temp; #endif c = get_symbol_end (); *input_line_pointer = c; @@ -7091,7 +7056,6 @@ pa_procend (unused) pa_undefine_label (); } - #ifdef OBJ_SOM /* If VALUE is an exact power of two between zero and 2^31, then return log2 (VALUE). Else return -1. */ @@ -7134,7 +7098,7 @@ pa_parse_space_stmt (space_name, create_flag) { char *name, *ptemp, c; char loadable, defined, private, sort; - int spnum, temp; + int spnum; asection *seg = NULL; sd_chain_struct *space; @@ -7168,10 +7132,11 @@ pa_parse_space_stmt (space_name, create_flag) /* First see if the space was specified as a number rather than as a name. According to the PA assembly manual the rest of the line should be ignored. */ - temp = pa_parse_number (&ptemp, 0); - if (temp >= 0) + strict = 0; + pa_parse_number (&ptemp, 0); + if (pa_number >= 0) { - spnum = temp; + spnum = pa_number; input_line_pointer = ptemp; } else @@ -7253,7 +7218,6 @@ pa_space (unused) int unused ATTRIBUTE_UNUSED; { char *name, c, *space_name, *save_s; - int temp; sd_chain_struct *sd_chain; if (within_procedure) @@ -7331,9 +7295,11 @@ pa_space (unused) /* It could be a space specified by number. */ print_errors = 0; save_s = input_line_pointer; - if ((temp = pa_parse_number (&input_line_pointer, 0)) >= 0) + strict = 0; + pa_parse_number (&input_line_pointer, 0); + if (pa_number >= 0) { - if ((sd_chain = pa_find_space_by_number (temp))) + if ((sd_chain = pa_find_space_by_number (pa_number))) { current_space = sd_chain; @@ -7618,7 +7584,6 @@ pa_subspace (create_new) SUBSPACE_DEFINED (current_subspace) = 1; } - /* Create default space and subspace dictionaries. */ static void @@ -7661,7 +7626,6 @@ pa_spaces_begin () /* Create the new section. */ segment = subseg_new (name, subsegment); - /* For SOM we want to replace the standard .text, .data, and .bss sections with our own. We also want to set BFD flags for all the built-in subspaces. */ @@ -7684,7 +7648,6 @@ pa_spaces_begin () | SEC_RELOC | SEC_HAS_CONTENTS)); - } else if (!strcmp (pa_def_subspaces[i].name, "$BSS$")) { @@ -7746,8 +7709,6 @@ pa_spaces_begin () } } - - /* Create a new space NAME, with the appropriate flags as defined by the given parameters. */ @@ -8344,6 +8305,16 @@ hppa_fix_adjustable (fixp) return 0; #endif +#ifdef OBJ_ELF + if (fixp->fx_r_type == (int) R_PARISC_GNU_VTINHERIT + || fixp->fx_r_type == (int) R_PARISC_GNU_VTENTRY) + return 0; +#endif + + if (fixp->fx_addsy && (S_IS_EXTERNAL (fixp->fx_addsy) + || S_IS_WEAK (fixp->fx_addsy))) + return 0; + /* Reject reductions of symbols in sym1-sym2 expressions when the fixup will occur in a CODE subspace. @@ -8373,19 +8344,20 @@ hppa_fix_adjustable (fixp) eg. Suppose we have . ldil LR%foo+0,%r21 . ldw RR%foo+0(%r21),%r26 - . ldw RR%foo+10(%r21),%r25 - - If foo is at address 4090 (decimal) in section `sect', then after - reducing to the section symbol, we get - . LR%sect+4090 == L%sect+0 - . RR%sect+4090 == R%sect+4090 - . RR%sect+4100 == R%sect-4092 (4100 - 8192) - and the last address loses. - - Obviously, 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 addends involved in LR% field selectors to work around a - HP linker bug. ie. We often have addresses like the last case + . ldw RR%foo+4(%r21),%r25 + + If foo is at address 4092 (decimal) in section `sect', then after + reducing to the section symbol we get + . LR%sect+4092 == (L%sect)+0 + . 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. + + 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 + addends involved in LR% field selectors to work around a HP + linker bug. ie. We often have addresses like the last case above where the LR% expression is offset from the RR% one. */ if (hppa_fix->fx_r_field == e_lrsel @@ -8403,18 +8375,15 @@ hppa_fix_adjustable (fixp) || hppa_fix->fx_r_field == e_lpsel) return 0; - if (fixp->fx_addsy && S_IS_EXTERNAL (fixp->fx_addsy)) - return 0; - /* Reject absolute calls (jumps). */ if (hppa_fix->fx_r_type == R_HPPA_ABS_CALL) return 0; /* Reject reductions of function symbols. */ - if (fixp->fx_addsy == 0 || ! S_IS_FUNCTION (fixp->fx_addsy)) - return 1; + if (fixp->fx_addsy != 0 && S_IS_FUNCTION (fixp->fx_addsy)) + return 0; - return 0; + return 1; } /* Return nonzero if the fixup in FIXP will require a relocation, @@ -8426,7 +8395,6 @@ hppa_force_relocation (fixp) struct fix *fixp; { struct hppa_fix_struct *hppa_fixp; - int distance; hppa_fixp = (struct hppa_fix_struct *) fixp->tc_fix_data; #ifdef OBJ_SOM @@ -8440,21 +8408,42 @@ hppa_force_relocation (fixp) && (hppa_fixp->segment->flags & SEC_CODE) != 0)) return 1; #endif +#ifdef OBJ_ELF + if (fixp->fx_r_type == (int) R_PARISC_GNU_VTINHERIT + || fixp->fx_r_type == (int) R_PARISC_GNU_VTENTRY) + return 1; +#endif + + assert (fixp->fx_addsy != NULL); + + /* Ensure we emit a relocation for global symbols so that dynamic + linking works. */ + if (S_IS_EXTERNAL (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)) + return 1; /* It is necessary to force PC-relative calls/jumps to have a relocation entry if they're going to need either a argument relocation or long - call stub. FIXME. Can't we need the same for absolute calls? */ - if (fixp->fx_pcrel && fixp->fx_addsy - && (arg_reloc_stub_needed (symbol_arg_reloc_info (fixp->fx_addsy), - hppa_fixp->fx_arg_reloc))) + call stub. */ + if (fixp->fx_pcrel + && arg_reloc_stub_needed (symbol_arg_reloc_info (fixp->fx_addsy), + hppa_fixp->fx_arg_reloc)) return 1; - distance = (fixp->fx_offset + S_GET_VALUE (fixp->fx_addsy) - - md_pcrel_from (fixp)); - /* Now check and see if we're going to need a long-branch stub. */ - if (fixp->fx_r_type == (int) R_HPPA_PCREL_CALL - && (distance > 262143 || distance < -262144)) - return 1; + /* Now check to see if we're going to need a long-branch stub. */ + if (fixp->fx_r_type == (int) R_HPPA_PCREL_CALL) + { + valueT distance; + + distance = (fixp->fx_offset + S_GET_VALUE (fixp->fx_addsy) + - md_pcrel_from (fixp) - 8); + if (distance + 8388608 >= 16777216 + || (hppa_fixp->fx_r_format == 17 && distance + 262144 >= 524288) +#ifdef OBJ_ELF + || (hppa_fixp->fx_r_format == 12 && distance + 8192 >= 16384) +#endif + ) + return 1; + } if (fixp->fx_r_type == (int) R_HPPA_ABS_CALL) return 1; @@ -8550,10 +8539,47 @@ elf_hppa_final_processing () } } -void -pa_end_of_source () +static void +pa_vtable_entry (ignore) + int ignore ATTRIBUTE_UNUSED; +{ + struct fix *new_fix; + + new_fix = obj_elf_vtable_entry (0); + + if (new_fix) + { + struct hppa_fix_struct *hppa_fix = (struct hppa_fix_struct *) + obstack_alloc (¬es, sizeof (struct hppa_fix_struct)); + hppa_fix->fx_r_type = R_HPPA; + hppa_fix->fx_r_field = e_fsel; + hppa_fix->fx_r_format = 32; + hppa_fix->fx_arg_reloc = 0; + hppa_fix->segment = now_seg; + new_fix->tc_fix_data = (void *) hppa_fix; + new_fix->fx_r_type = (int) R_PARISC_GNU_VTENTRY; + } +} + +static void +pa_vtable_inherit (ignore) + int ignore ATTRIBUTE_UNUSED; { - if (debug_type == DEBUG_DWARF2) - dwarf2_finish (); + struct fix *new_fix; + + new_fix = obj_elf_vtable_inherit (0); + + if (new_fix) + { + struct hppa_fix_struct *hppa_fix = (struct hppa_fix_struct *) + obstack_alloc (¬es, sizeof (struct hppa_fix_struct)); + hppa_fix->fx_r_type = R_HPPA; + hppa_fix->fx_r_field = e_fsel; + hppa_fix->fx_r_format = 32; + hppa_fix->fx_arg_reloc = 0; + hppa_fix->segment = now_seg; + new_fix->tc_fix_data = (void *) hppa_fix; + new_fix->fx_r_type = (int) R_PARISC_GNU_VTINHERIT; + } } #endif