Support more relocs on 16-bit insn fields

This patch allows gas to assemble a testcase like
	li 3,ext_sym
which oddly was not accepted while the following is OK:
	li 3,ext_sym@l

	* config/tc-ppc.c (md_assemble): Move code adjusting reloc types
	later.  Merge absolute and relative branch reloc selection.
	Generate 16-bit relocs for most 16-bit insn fields given a
	non-constant expression.
This commit is contained in:
Alan Modra
2014-03-05 19:31:45 +10:30
parent f50c47f118
commit a0593ad956
2 changed files with 116 additions and 116 deletions

View File

@ -1,3 +1,10 @@
2014-03-05 Alan Modra <amodra@gmail.com>
* config/tc-ppc.c (md_assemble): Move code adjusting reloc types
later. Merge absolute and relative branch reloc selection.
Generate 16-bit relocs for most 16-bit insn fields given a
non-constant expression.
2014-03-05 Alan Modra <amodra@gmail.com>
* config/tc-ppc.c (ppc_is_toc_sym): Remove OBJ_ELF support.

View File

@ -3133,6 +3133,48 @@ md_assemble (char *str)
break;
}
}
}
#endif /* OBJ_ELF */
if (reloc != BFD_RELOC_UNUSED)
;
/* Determine a BFD reloc value based on the operand information.
We are only prepared to turn a few of the operands into
relocs. */
else if ((operand->flags & (PPC_OPERAND_RELATIVE
| PPC_OPERAND_ABSOLUTE)) != 0
&& operand->bitm == 0x3fffffc
&& operand->shift == 0)
reloc = BFD_RELOC_PPC_B26;
else if ((operand->flags & (PPC_OPERAND_RELATIVE
| PPC_OPERAND_ABSOLUTE)) != 0
&& operand->bitm == 0xfffc
&& operand->shift == 0)
reloc = BFD_RELOC_PPC_B16;
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
&& operand->bitm == 0x1fe
&& operand->shift == -1)
reloc = BFD_RELOC_PPC_VLE_REL8;
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
&& operand->bitm == 0xfffe
&& operand->shift == 0)
reloc = BFD_RELOC_PPC_VLE_REL15;
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
&& operand->bitm == 0x1fffffe
&& operand->shift == 0)
reloc = BFD_RELOC_PPC_VLE_REL24;
else if ((operand->flags & PPC_OPERAND_NEGATIVE) == 0
&& (operand->bitm & 0xfff0) == 0xfff0
&& operand->shift == 0)
{
reloc = BFD_RELOC_16;
#ifdef OBJ_XCOFF
/* Note: the symbol may be not yet defined. */
if ((operand->flags & PPC_OPERAND_PARENS) != 0
&& ppc_is_toc_sym (ex.X_add_symbol))
reloc = BFD_RELOC_PPC_TOC16;
#endif
}
/* For the absolute forms of branches, convert the PC
relative form back into the absolute. */
@ -3146,17 +3188,20 @@ md_assemble (char *str)
case BFD_RELOC_PPC_B16:
reloc = BFD_RELOC_PPC_BA16;
break;
#ifdef OBJ_ELF
case BFD_RELOC_PPC_B16_BRTAKEN:
reloc = BFD_RELOC_PPC_BA16_BRTAKEN;
break;
case BFD_RELOC_PPC_B16_BRNTAKEN:
reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;
break;
#endif
default:
break;
}
}
#ifdef OBJ_ELF
switch (reloc)
{
case BFD_RELOC_PPC_TOC16:
@ -3171,7 +3216,8 @@ md_assemble (char *str)
break;
}
if ((operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
if (ppc_obj64
&& (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
{
switch (reloc)
{
@ -3230,60 +3276,7 @@ md_assemble (char *str)
break;
}
}
}
#endif /* OBJ_ELF */
if (reloc != BFD_RELOC_UNUSED)
;
/* Determine a BFD reloc value based on the operand information.
We are only prepared to turn a few of the operands into
relocs. */
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
&& operand->bitm == 0x3fffffc
&& operand->shift == 0)
reloc = BFD_RELOC_PPC_B26;
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
&& operand->bitm == 0xfffc
&& operand->shift == 0)
reloc = BFD_RELOC_PPC_B16;
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
&& operand->bitm == 0x1fe
&& operand->shift == -1)
reloc = BFD_RELOC_PPC_VLE_REL8;
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
&& operand->bitm == 0xfffe
&& operand->shift == 0)
reloc = BFD_RELOC_PPC_VLE_REL15;
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
&& operand->bitm == 0x1fffffe
&& operand->shift == 0)
reloc = BFD_RELOC_PPC_VLE_REL24;
else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
&& operand->bitm == 0x3fffffc
&& operand->shift == 0)
reloc = BFD_RELOC_PPC_BA26;
else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
&& operand->bitm == 0xfffc
&& operand->shift == 0)
reloc = BFD_RELOC_PPC_BA16;
#if defined (OBJ_XCOFF) || defined (OBJ_ELF)
else if ((operand->flags & PPC_OPERAND_PARENS) != 0
&& (operand->bitm & 0xfff0) == 0xfff0
&& operand->shift == 0)
{
reloc = BFD_RELOC_16;
#ifdef OBJ_ELF
if (ppc_obj64
&& (operand->flags & PPC_OPERAND_DS) != 0)
reloc = BFD_RELOC_PPC64_ADDR16_DS;
#endif
#ifdef OBJ_XCOFF
/* Note: the symbol may be not yet defined. */
if (ppc_is_toc_sym (ex.X_add_symbol))
reloc = BFD_RELOC_PPC_TOC16;
#endif
}
#endif /* defined (OBJ_XCOFF) || defined (OBJ_ELF) */
/* We need to generate a fixup for this expression. */
if (fc >= MAX_INSN_FIXUPS)