/* tc-hppa.c -- Assemble for the PA
- Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
+ Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ 2002, 2003 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
#if TARGET_ARCH_SIZE == 64
/* How to generate a relocation. */
#define hppa_gen_reloc_type _bfd_elf64_hppa_gen_reloc_type
+#define elf_hppa_reloc_final_type elf64_hppa_reloc_final_type
#else
#define hppa_gen_reloc_type _bfd_elf32_hppa_gen_reloc_type
+#define elf_hppa_reloc_final_type elf32_hppa_reloc_final_type
#endif
/* ELF objects can have versions, but apparently do not have anywhere
/* handle of the OPCODE hash table */
static struct hash_control *op_hash = NULL;
+/* These characters can be suffixes of opcode names and they may be
+ followed by meaningful whitespace. We don't include `,' and `!'
+ as they never appear followed by meaningful whitespace. */
+const char hppa_symbol_chars[] = "*?=<>";
+
/* Table of pseudo ops for the PA. FIXME -- how many of these
are now redundant with the overall GAS and the object file
dependent tables? */
{"equ", pa_equ, 0},
{"exit", pa_exit, 0},
{"export", pa_export, 0},
-#ifdef OBJ_ELF
- {"file", dwarf2_directive_file, 0 },
-#endif
{"fill", pa_fill, 0},
{"float", pa_float_cons, 'f'},
{"half", pa_cons, 2},
{"lcomm", pa_lcomm, 0},
{"leave", pa_leave, 0},
{"level", pa_level, 0},
-#ifdef OBJ_ELF
- {"loc", dwarf2_directive_loc, 0 },
-#endif
{"long", pa_cons, 4},
{"lsym", pa_lsym, 0},
#ifdef OBJ_SOM
{
if (1
#ifdef OBJ_SOM
- && current_space == label_chain->lss_space && label_chain->lss_label
+ && current_space == label_chain->lss_space && label_chain->lss_label
#endif
#ifdef OBJ_ELF
- && now_seg == label_chain->lss_segment && label_chain->lss_label
+ && now_seg == label_chain->lss_segment && label_chain->lss_label
#endif
)
{
args++;
switch (*args)
{
- /* Handle FP compare conditions. */
- case 'f':
- cond = pa_parse_fp_cmp_cond (&s);
- INSERT_FIELD_AND_CONTINUE (opcode, cond, 0);
+ /* Handle FP compare conditions. */
+ case 'f':
+ cond = pa_parse_fp_cmp_cond (&s);
+ INSERT_FIELD_AND_CONTINUE (opcode, cond, 0);
/* Handle an add condition. */
case 'A':
case 'a':
- cmpltr = 0;
- flag = 0;
+ cmpltr = 0;
+ flag = 0;
if (*s == ',')
{
s++;
the_insn.pcrel = 1;
if (!the_insn.exp.X_add_symbol
|| !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
- "L$0\001"))
+ FAKE_LABEL_NAME))
{
num = evaluate_absolute (&the_insn);
if (num % 4)
the_insn.pcrel = 1;
if (!the_insn.exp.X_add_symbol
|| !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
- "L$0\001"))
+ FAKE_LABEL_NAME))
{
num = evaluate_absolute (&the_insn);
if (num % 4)
the_insn.pcrel = 1;
if (!the_insn.exp.X_add_symbol
|| !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
- "L$0\001"))
+ FAKE_LABEL_NAME))
{
num = evaluate_absolute (&the_insn);
if (num % 4)
the_insn.pcrel = 0;
if (!the_insn.exp.X_add_symbol
|| !strcmp (S_GET_NAME (the_insn.exp.X_add_symbol),
- "L$0\001"))
+ FAKE_LABEL_NAME))
{
num = evaluate_absolute (&the_insn);
if (num % 4)
failed:
/* Check if the args matched. */
- if (match == FALSE)
+ if (!match)
{
if (&insn[1] - pa_opcodes < (int) NUMOPCODES
&& !strcmp (insn->name, insn[1].name))
case R_N0SEL:
case R_N1SEL:
/* There is no symbol or addend associated with these fixups. */
- relocs[i]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
- *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
+ relocs[i]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
relocs[i]->addend = 0;
break;
case R_ENTRY:
case R_EXIT:
/* There is no symbol associated with these fixups. */
- relocs[i]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
- *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
+ relocs[i]->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+ *relocs[i]->sym_ptr_ptr = symbol_get_bfdsym (dummy_symbol);
relocs[i]->addend = fixp->fx_offset;
break;
offsetT new_val;
int insn, val, fmt;
- if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
- fixP->fx_done = 1;
-
/* 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. */
return;
#endif
+ 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. */
hppa_fixP = (struct hppa_fix_struct *) fixP->tc_fix_data;
return;
}
- buf = fixP->fx_frag->fr_literal + fixP->fx_where;
+ buf = (unsigned char *) (fixP->fx_frag->fr_literal + fixP->fx_where);
insn = bfd_get_32 (stdoutput, buf);
fmt = bfd_hppa_insn2fmt (stdoutput, insn);
|| 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);
symbolS *sym;
int status;
char *p = *s;
- boolean have_prefix;
+ bfd_boolean have_prefix;
/* Skip whitespace before the number. */
while (*p == ' ' || *p == '\t')
num = S_GET_VALUE (sym);
/* Well, we don't really have one, but we do have a
register, so... */
- have_prefix = true;
+ have_prefix = TRUE;
}
else if (S_GET_SEGMENT (sym) == &bfd_abs_section)
num = S_GET_VALUE (sym);
input_line_pointer = *strp;
s = *strp;
while (*s != ',' && *s != ' ' && *s != '\t')
- s++;
+ s++;
c = *s;
*s = 0;
hppa_fix_adjustable (fixp)
fixS *fixp;
{
+ reloc_type code;
struct hppa_fix_struct *hppa_fix;
hppa_fix = (struct hppa_fix_struct *) fixp->tc_fix_data;
#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;
+ /* 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)
+ even if they occur with a different selector. */
+ code = elf_hppa_reloc_final_type (stdoutput, fixp->fx_r_type,
+ hppa_fix->fx_r_format,
+ hppa_fix->fx_r_field);
+
+ switch (code)
+ {
+ /* Relocation types which use e_lrsel. */
+ case R_PARISC_DIR21L:
+ case R_PARISC_DLTREL21L:
+ case R_PARISC_DPREL21L:
+ case R_PARISC_PLTOFF21L:
+
+ /* Relocation types which use e_rrsel. */
+ case R_PARISC_DIR14R:
+ case R_PARISC_DIR14DR:
+ case R_PARISC_DIR14WR:
+ case R_PARISC_DIR17R:
+ case R_PARISC_DLTREL14R:
+ case R_PARISC_DLTREL14DR:
+ case R_PARISC_DLTREL14WR:
+ case R_PARISC_DPREL14R:
+ case R_PARISC_DPREL14DR:
+ case R_PARISC_DPREL14WR:
+ case R_PARISC_PLTOFF14R:
+ case R_PARISC_PLTOFF14DR:
+ case R_PARISC_PLTOFF14WR:
+
+ /* Other types that we reject for reduction. */
+ case R_PARISC_GNU_VTENTRY:
+ case R_PARISC_GNU_VTINHERIT:
+ return 0;
+ default:
+ break;
+ }
#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.
if (fixp->fx_addsy
&& fixp->fx_subsy
&& (hppa_fix->segment->flags & SEC_CODE))
- {
- /* Apparently sy_used_in_reloc never gets set for sub symbols. */
- symbol_mark_used_in_reloc (fixp->fx_subsy);
- return 0;
- }
+ return 0;
/* We can't adjust any relocs that use LR% and RR% field selectors.
/* 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))
+ if (S_FORCE_RELOC (fixp->fx_addsy, 1))
return 1;
/* It is necessary to force PC-relative calls/jumps to have a relocation
/* 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;
+ long pc = md_pcrel_from (fixp);
+ valueT distance, min_stub_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)
+ distance = fixp->fx_offset + S_GET_VALUE (fixp->fx_addsy) - pc - 8;
+
+ /* Distance to the closest possible stub. This will detect most
+ but not all circumstances where a stub will not work. */
+ min_stub_distance = pc + 16;
+#ifdef OBJ_SOM
+ if (last_call_info != NULL)
+ min_stub_distance -= S_GET_VALUE (last_call_info->start_symbol);
#endif
+
+ if ((distance + 8388608 >= 16777216
+ && min_stub_distance <= 8388608)
+ || (hppa_fixp->fx_r_format == 17
+ && distance + 262144 >= 524288
+ && min_stub_distance <= 262144)
+ || (hppa_fixp->fx_r_format == 12
+ && distance + 8192 >= 16384
+ && min_stub_distance <= 8192)
)
return 1;
}
/* Now for some ELF specific code. FIXME. */
#ifdef OBJ_ELF
/* Mark the end of a function so that it's possible to compute
- the size of the function in hppa_elf_final_processing. */
+ the size of the function in elf_hppa_final_processing. */
static void
hppa_elf_mark_end_of_function ()