External/weak SOM fixes, branch limit corrections.

This commit is contained in:
Alan Modra 2000-09-27 16:50:39 +00:00
parent a17cc40f09
commit 5506e1a5d8
2 changed files with 64 additions and 33 deletions

View File

@ -1,3 +1,18 @@
2000-09-28 Alan Modra <alan@linuxcare.com.au>
* config/tc-hppa.c (md_apply_fix): Add fmt assertion. Don't
adjust for external and weak syms as we will use a reloc. Allow
for +8 offset when calculating limits of branches.
(hppa_fix_adjustable): Undo 2000-09-23 change.
(hppa_force_relocation): Likewise. Add fx_addsy assertion.
Correct distance calculation.
From John David Anglin <dave@hiauly1.hia.nrc.ca>
* config/tc-hppa.c (nonzero_dibits): Define.
(arg_reloc_stub_needed): Check each arg and return value
separately for zero case.
(pa_align): Declare argument `bytes'.
2000-09-25 Kazu Hirata <kazu@hxi.com>
* config/tc-cris.c: Fix formatting.

View File

@ -4011,7 +4011,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++)
;
@ -4323,8 +4326,10 @@ md_undefined_symbol (name)
}
#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
@ -4375,6 +4380,8 @@ md_apply_fix (fixP, valp)
{
int fmt = bfd_hppa_insn2fmt (stdoutput, insn);
assert (fmt == hppa_fixP->fx_r_format);
/* 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
@ -4412,9 +4419,11 @@ md_apply_fix (fixP, valp)
&& 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))
&& ((*valp - 8 + 8192) < 16384
|| (fmt == 17 && (*valp - 8 + 262144) < 524288)
|| (fmt == 22 && (*valp - 8 + 8388608) < 16777216))
&& !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))
@ -4464,10 +4473,10 @@ md_apply_fix (fixP, valp)
/* Handle all the opcodes with the 'w' operand type. */
case 12:
CHECK_FIELD (new_val, 8199, -8184, 0);
val = new_val;
CHECK_FIELD (new_val - 8, 8191, -8192, 0);
val = new_val - 8;
insn = (insn & ~ 0x1ffd) | re_assemble_12 ((val - 8) >> 2);
insn = (insn & ~ 0x1ffd) | re_assemble_12 (val >> 2);
break;
/* Handle some of the opcodes with the 'W' operand type. */
@ -4479,12 +4488,12 @@ md_apply_fix (fixP, valp)
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);
CHECK_FIELD (distance - 8, 262143, -262144, 0);
CHECK_FIELD (new_val, 262143, -262144, 0);
val = new_val;
CHECK_FIELD (new_val - 8, 262143, -262144, 0);
val = new_val - 8;
insn = (insn & ~ 0x1f1ffd) | re_assemble_17 ((val - 8) >> 2);
insn = (insn & ~ 0x1f1ffd) | re_assemble_17 (val >> 2);
break;
}
@ -4496,12 +4505,12 @@ md_apply_fix (fixP, valp)
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);
CHECK_FIELD (distance - 8, 8388607, -8388608, 0);
CHECK_FIELD (new_val, 8388607, -8388608, 0);
val = new_val;
CHECK_FIELD (new_val - 8, 8388607, -8388608, 0);
val = new_val - 8;
insn = (insn & ~ 0x3ff1ffd) | re_assemble_22 ((val - 8) >> 2);
insn = (insn & ~ 0x3ff1ffd) | re_assemble_22 (val >> 2);
break;
}
@ -5827,6 +5836,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 ();
@ -8310,11 +8320,11 @@ hppa_fix_adjustable (fixp)
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;
#endif
/* Reject reductions of symbols in sym1-sym2 expressions when
the fixup will occur in a CODE subspace.
@ -8381,10 +8391,10 @@ hppa_fix_adjustable (fixp)
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,
@ -8396,7 +8406,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
@ -8414,28 +8423,35 @@ hppa_force_relocation (fixp)
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 (fixp->fx_addsy && (S_IS_EXTERNAL (fixp->fx_addsy)
|| S_IS_WEAK (fixp->fx_addsy)))
if (S_IS_EXTERNAL (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy))
return 1;
#endif
/* 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. */
if (fixp->fx_pcrel && fixp->fx_addsy
&& (arg_reloc_stub_needed (symbol_arg_reloc_info (fixp->fx_addsy),
hppa_fixp->fx_arg_reloc)))
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)
|| (hppa_fixp->fx_r_format == 12 && distance + 8192 >= 16384))
return 1;
}
if (fixp->fx_r_type == (int) R_HPPA_ABS_CALL)
return 1;