This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: FYI: patches for powerpc-aix...
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org, rsandifo at linux dot vnet dot ibm dot com
- Date: Mon, 20 May 2013 19:45:43 +0930
- Subject: Re: FYI: patches for powerpc-aix...
- References: <20130218230528 dot GH22159 at adacore dot com> <20130219024126 dot GI1266 at bubble dot grove dot modra dot org> <4C5A0934-EF54-4A9F-A4BF-EF56E098B3CC at adacore dot com> <20130515235945 dot GE5221 at bubble dot grove dot modra dot org> <51691E90-E8F7-4EBE-8CF7-BF50EA2DDCD8 at adacore dot com> <87zjvv3x50 dot fsf at sandifor-thinkpad dot stglab dot manchester dot uk dot ibm dot com> <20130517052307 dot GI5221 at bubble dot grove dot modra dot org> <877gix1xoi dot fsf at sandifor-thinkpad dot stglab dot manchester dot uk dot ibm dot com>
On Fri, May 17, 2013 at 03:35:41PM +0100, Richard Sandiford wrote:
> If you think the md_apply_fix change is worth keeping as a cleanup,
> then FWIW, here's the patch with just that part. Tested as before.
When reviewing this patch in detail, I noticed that it manages to lose
some pc-relative error checking. Fixing that required pulling things
apart, so much so that I've rewritten the whole thing. I moved the
pc-relative processing later since it is really only relevant when
emitting a reloc.
* config/tc-ppc.c (md_apply_fix): Hoist code common to insn
and data fixups performing shift/high adjust/sign extension on
fieldval. Sink fx_pcrel handling and checks. Use fixP->fx_size
when writing data fixups rather than recalculating size.
Index: gas/config/tc-ppc.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ppc.c,v
retrieving revision 1.198
diff -u -p -r1.198 tc-ppc.c
--- gas/config/tc-ppc.c 16 May 2013 15:41:40 -0000 1.198
+++ gas/config/tc-ppc.c 18 May 2013 07:06:14 -0000
@@ -6287,6 +6287,8 @@ void
md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
valueT value = * valP;
+ offsetT fieldval;
+ const struct powerpc_operand *operand;
#ifdef OBJ_ELF
if (fixP->fx_addsy != NULL)
@@ -6325,16 +6327,13 @@ md_apply_fix (fixS *fixP, valueT *valP,
as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
}
+ operand = NULL;
if (fixP->fx_pcrel_adjust != 0)
{
- /* Handle relocs in an insn. */
-
+ /* This is a fixup on an instruction. */
int opindex = fixP->fx_pcrel_adjust & 0xff;
- const struct powerpc_operand *operand = &powerpc_operands[opindex];
- char *where;
- unsigned long insn;
- offsetT fieldval;
+ operand = &powerpc_operands[opindex];
#ifdef OBJ_XCOFF
/* An instruction like `lwz 9,sym(30)' when `sym' is not a TOC symbol
does not generate a reloc. It uses the offset of `sym' within its
@@ -6354,74 +6353,75 @@ md_apply_fix (fixS *fixP, valueT *valP,
fixP->fx_done = 1;
}
#endif
- fieldval = value;
- switch (fixP->fx_r_type)
- {
+ }
+
+ /* Calculate value to be stored in field. */
+ fieldval = value;
+ switch (fixP->fx_r_type)
+ {
#ifdef OBJ_ELF
- case BFD_RELOC_PPC64_ADDR16_LO_DS:
- if (fixP->fx_pcrel)
- goto bad_pcrel;
- /* fall through */
+ case BFD_RELOC_PPC64_ADDR16_LO_DS:
+ case BFD_RELOC_PPC_VLE_LO16A:
+ case BFD_RELOC_PPC_VLE_LO16D:
#endif
- case BFD_RELOC_LO16:
- if (fixP->fx_pcrel)
- fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
- /* fall through */
- case BFD_RELOC_LO16_PCREL:
- case BFD_RELOC_PPC_VLE_LO16A:
- case BFD_RELOC_PPC_VLE_LO16D:
- fieldval = value & 0xffff;
- sign_extend_16:
- if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
- fieldval = (fieldval ^ 0x8000) - 0x8000;
- fixP->fx_no_overflow = 1;
- break;
-
- case BFD_RELOC_HI16:
- if (fixP->fx_pcrel)
- fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
- /* fall through */
- case BFD_RELOC_HI16_PCREL:
- case BFD_RELOC_PPC_VLE_HI16A:
- case BFD_RELOC_PPC_VLE_HI16D:
- fieldval = PPC_HI (value);
- goto sign_extend_16;
+ case BFD_RELOC_LO16:
+ case BFD_RELOC_LO16_PCREL:
+ fieldval = value & 0xffff;
+ sign_extend_16:
+ if (operand != NULL && (operand->flags & PPC_OPERAND_SIGNED) != 0)
+ fieldval = (fieldval ^ 0x8000) - 0x8000;
+ fixP->fx_no_overflow = 1;
+ break;
- case BFD_RELOC_HI16_S:
- if (fixP->fx_pcrel)
- fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
- /* fall through */
- case BFD_RELOC_HI16_S_PCREL:
- case BFD_RELOC_PPC_VLE_HA16A:
- case BFD_RELOC_PPC_VLE_HA16D:
- fieldval = PPC_HA (value);
- goto sign_extend_16;
+#ifdef OBJ_ELF
+ case BFD_RELOC_PPC_VLE_HI16A:
+ case BFD_RELOC_PPC_VLE_HI16D:
+#endif
+ case BFD_RELOC_HI16:
+ case BFD_RELOC_HI16_PCREL:
+ fieldval = PPC_HI (value);
+ goto sign_extend_16;
#ifdef OBJ_ELF
- case BFD_RELOC_PPC64_HIGHER:
- if (fixP->fx_pcrel)
- goto bad_pcrel;
- fieldval = PPC_HIGHER (value);
- goto sign_extend_16;
+ case BFD_RELOC_PPC_VLE_HA16A:
+ case BFD_RELOC_PPC_VLE_HA16D:
+#endif
+ case BFD_RELOC_HI16_S:
+ case BFD_RELOC_HI16_S_PCREL:
+ fieldval = PPC_HA (value);
+ goto sign_extend_16;
- case BFD_RELOC_PPC64_HIGHER_S:
- if (fixP->fx_pcrel)
- goto bad_pcrel;
- fieldval = PPC_HIGHERA (value);
- goto sign_extend_16;
+#ifdef OBJ_ELF
+ case BFD_RELOC_PPC64_HIGHER:
+ fieldval = PPC_HIGHER (value);
+ goto sign_extend_16;
+
+ case BFD_RELOC_PPC64_HIGHER_S:
+ fieldval = PPC_HIGHERA (value);
+ goto sign_extend_16;
+
+ case BFD_RELOC_PPC64_HIGHEST:
+ fieldval = PPC_HIGHEST (value);
+ goto sign_extend_16;
+
+ case BFD_RELOC_PPC64_HIGHEST_S:
+ fieldval = PPC_HIGHESTA (value);
+ goto sign_extend_16;
+#endif
- case BFD_RELOC_PPC64_HIGHEST:
- if (fixP->fx_pcrel)
- goto bad_pcrel;
- fieldval = PPC_HIGHEST (value);
- goto sign_extend_16;
+ default:
+ break;
+ }
- case BFD_RELOC_PPC64_HIGHEST_S:
- if (fixP->fx_pcrel)
- goto bad_pcrel;
- fieldval = PPC_HIGHESTA (value);
- goto sign_extend_16;
+ if (operand != NULL)
+ {
+ /* Handle relocs in an insn. */
+ char *where;
+ unsigned long insn;
+#ifdef OBJ_ELF
+ switch (fixP->fx_r_type)
+ {
/* The following relocs can't be calculated by the assembler.
Leave the field zero. */
case BFD_RELOC_PPC_TPREL16:
@@ -6463,8 +6463,6 @@ md_apply_fix (fixS *fixP, valueT *valP,
gas_assert (fixP->fx_addsy != NULL);
S_SET_THREAD_LOCAL (fixP->fx_addsy);
fieldval = 0;
- if (fixP->fx_pcrel)
- goto bad_pcrel;
break;
/* These also should leave the field zero for the same
@@ -6531,14 +6529,12 @@ md_apply_fix (fixS *fixP, valueT *valP,
case BFD_RELOC_PPC_TLSGD:
case BFD_RELOC_PPC_TLSLD:
fieldval = 0;
- if (fixP->fx_pcrel)
- goto bad_pcrel;
break;
-#endif
default:
break;
}
+#endif
#ifdef OBJ_ELF
/* powerpc uses RELA style relocs, so if emitting a reloc the field
@@ -6610,79 +6606,9 @@ md_apply_fix (fixS *fixP, valueT *valP,
}
else
{
- int size = 0;
- offsetT fieldval = value;
-
/* Handle relocs in data. */
switch (fixP->fx_r_type)
{
- case BFD_RELOC_CTOR:
- if (ppc_obj64)
- goto ctor64;
- /* fall through */
-
- case BFD_RELOC_32:
- if (fixP->fx_pcrel)
- fixP->fx_r_type = BFD_RELOC_32_PCREL;
- /* fall through */
-
- case BFD_RELOC_32_PCREL:
- case BFD_RELOC_RVA:
- size = 4;
- break;
-
- case BFD_RELOC_64:
- ctor64:
- if (fixP->fx_pcrel)
- fixP->fx_r_type = BFD_RELOC_64_PCREL;
- /* fall through */
-
- case BFD_RELOC_64_PCREL:
- size = 8;
- break;
-
- case BFD_RELOC_16:
- if (fixP->fx_pcrel)
- fixP->fx_r_type = BFD_RELOC_16_PCREL;
- /* fall through */
-
- case BFD_RELOC_16_PCREL:
- size = 2;
- break;
-
- case BFD_RELOC_8:
- if (fixP->fx_pcrel)
- {
-#ifdef OBJ_ELF
- bad_pcrel:
-#endif
- if (fixP->fx_addsy)
- {
- char *sfile;
- unsigned int sline;
-
- /* Use expr_symbol_where to see if this is an
- expression symbol. */
- if (expr_symbol_where (fixP->fx_addsy, &sfile, &sline))
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("unresolved expression that must"
- " be resolved"));
- else
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("cannot emit PC relative %s relocation"
- " against %s"),
- bfd_get_reloc_code_name (fixP->fx_r_type),
- S_GET_NAME (fixP->fx_addsy));
- }
- else
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("unable to resolve expression"));
- fixP->fx_done = 1;
- }
- else
- size = 1;
- break;
-
case BFD_RELOC_VTABLE_INHERIT:
if (fixP->fx_addsy
&& !S_IS_DEFINED (fixP->fx_addsy)
@@ -6697,54 +6623,15 @@ md_apply_fix (fixS *fixP, valueT *valP,
#ifdef OBJ_ELF
/* These can appear with @l etc. in data. */
case BFD_RELOC_LO16:
- if (fixP->fx_pcrel)
- fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
case BFD_RELOC_LO16_PCREL:
- size = 2;
- break;
-
case BFD_RELOC_HI16:
- if (fixP->fx_pcrel)
- fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
case BFD_RELOC_HI16_PCREL:
- size = 2;
- fieldval = PPC_HI (value);
- break;
-
case BFD_RELOC_HI16_S:
- if (fixP->fx_pcrel)
- fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
case BFD_RELOC_HI16_S_PCREL:
- size = 2;
- fieldval = PPC_HA (value);
- break;
-
case BFD_RELOC_PPC64_HIGHER:
- if (fixP->fx_pcrel)
- goto bad_pcrel;
- size = 2;
- fieldval = PPC_HIGHER (value);
- break;
-
case BFD_RELOC_PPC64_HIGHER_S:
- if (fixP->fx_pcrel)
- goto bad_pcrel;
- size = 2;
- fieldval = PPC_HIGHERA (value);
- break;
-
case BFD_RELOC_PPC64_HIGHEST:
- if (fixP->fx_pcrel)
- goto bad_pcrel;
- size = 2;
- fieldval = PPC_HIGHEST (value);
- break;
-
case BFD_RELOC_PPC64_HIGHEST_S:
- if (fixP->fx_pcrel)
- goto bad_pcrel;
- size = 2;
- fieldval = PPC_HIGHESTA (value);
break;
case BFD_RELOC_PPC_DTPMOD:
@@ -6835,8 +6722,17 @@ md_apply_fix (fixS *fixP, valueT *valP,
#ifdef OBJ_XCOFF
case BFD_RELOC_NONE:
- break;
#endif
+ case BFD_RELOC_CTOR:
+ case BFD_RELOC_32:
+ case BFD_RELOC_32_PCREL:
+ case BFD_RELOC_RVA:
+ case BFD_RELOC_64:
+ case BFD_RELOC_64_PCREL:
+ case BFD_RELOC_16:
+ case BFD_RELOC_16_PCREL:
+ case BFD_RELOC_8:
+ break;
default:
fprintf (stderr,
@@ -6845,9 +6741,85 @@ md_apply_fix (fixS *fixP, valueT *valP,
abort ();
}
- if (size && APPLY_RELOC)
+ if (fixP->fx_size && APPLY_RELOC)
md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
- fieldval, size);
+ fieldval, fixP->fx_size);
+ }
+
+ /* We are only able to convert some relocs to pc-relative. */
+ if (!fixP->fx_done && fixP->fx_pcrel)
+ {
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_LO16:
+ fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
+ break;
+
+ case BFD_RELOC_HI16:
+ fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
+ break;
+
+ case BFD_RELOC_HI16_S:
+ fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
+ break;
+
+ case BFD_RELOC_64:
+ fixP->fx_r_type = BFD_RELOC_64_PCREL;
+ break;
+
+ case BFD_RELOC_32:
+ fixP->fx_r_type = BFD_RELOC_32_PCREL;
+ break;
+
+ case BFD_RELOC_16:
+ fixP->fx_r_type = BFD_RELOC_16_PCREL;
+ break;
+
+ /* Some of course are already pc-relative. */
+ case BFD_RELOC_LO16_PCREL:
+ case BFD_RELOC_HI16_PCREL:
+ case BFD_RELOC_HI16_S_PCREL:
+ case BFD_RELOC_64_PCREL:
+ case BFD_RELOC_32_PCREL:
+ case BFD_RELOC_16_PCREL:
+ case BFD_RELOC_PPC_B16:
+ case BFD_RELOC_PPC_B16_BRTAKEN:
+ case BFD_RELOC_PPC_B16_BRNTAKEN:
+ case BFD_RELOC_PPC_B26:
+ case BFD_RELOC_PPC_LOCAL24PC:
+ case BFD_RELOC_24_PLT_PCREL:
+ case BFD_RELOC_32_PLT_PCREL:
+ case BFD_RELOC_64_PLT_PCREL:
+ case BFD_RELOC_PPC_VLE_REL8:
+ case BFD_RELOC_PPC_VLE_REL15:
+ case BFD_RELOC_PPC_VLE_REL24:
+ break;
+
+ default:
+ if (fixP->fx_addsy)
+ {
+ char *sfile;
+ unsigned int sline;
+
+ /* Use expr_symbol_where to see if this is an
+ expression symbol. */
+ if (expr_symbol_where (fixP->fx_addsy, &sfile, &sline))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("unresolved expression that must"
+ " be resolved"));
+ else
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("cannot emit PC relative %s relocation"
+ " against %s"),
+ bfd_get_reloc_code_name (fixP->fx_r_type),
+ S_GET_NAME (fixP->fx_addsy));
+ }
+ else
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("unable to resolve expression"));
+ fixP->fx_done = 1;
+ break;
+ }
}
#ifdef OBJ_ELF
--
Alan Modra
Australia Development Lab, IBM