diff options
Diffstat (limited to 'gas/config/tc-sh.c')
-rw-r--r-- | gas/config/tc-sh.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/gas/config/tc-sh.c b/gas/config/tc-sh.c index 0d098d2..ac6e17f 100644 --- a/gas/config/tc-sh.c +++ b/gas/config/tc-sh.c @@ -4018,6 +4018,23 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) break; case BFD_RELOC_SH_PCRELIMM8BY4: + /* If we are dealing with a known destination ... */ + if ((fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy)) + && (fixP->fx_subsy == NULL || S_IS_DEFINED (fixP->fx_addsy))) + { + /* Don't silently move the destination due to misalignment. + The absolute address is the fragment base plus the offset into + the fragment plus the pc relative offset to the label. */ + if ((fixP->fx_frag->fr_address + fixP->fx_where + val) & 3) + as_bad_where (fixP->fx_file, fixP->fx_line, + _("offset to unaligned destination")); + + /* The displacement cannot be zero or backward even if aligned. + Allow -2 because val has already been adjusted somewhere. */ + if (val < -2) + as_bad_where (fixP->fx_file, fixP->fx_line, _("negative offset")); + } + /* The lower two bits of the PC are cleared before the displacement is added in. We can assume that the destination is on a 4 byte boundary. If this instruction is also on a 4 |