aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meissner <gnu@the-meissners.org>1995-08-21 17:47:01 +0000
committerMichael Meissner <gnu@the-meissners.org>1995-08-21 17:47:01 +0000
commit840886d875b1338c734dd655b957549d1a62122a (patch)
treebea05fd3c1997045782cafcb02e0dde0df6dad2a
parent68807a39e419aeceff65520dcd8869a29611e7d8 (diff)
downloadgdb-840886d875b1338c734dd655b957549d1a62122a.zip
gdb-840886d875b1338c734dd655b957549d1a62122a.tar.gz
gdb-840886d875b1338c734dd655b957549d1a62122a.tar.bz2
Allow @HA, @L, and @H on constant expressions.
-rw-r--r--gas/ChangeLog5
-rw-r--r--gas/config/tc-ppc.c81
2 files changed, 75 insertions, 11 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 372915f..786bb16 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,8 @@
+Mon Aug 21 13:41:33 1995 Michael Meissner <meissner@cygnus.com>
+
+ * config/tc-ppc.c (md_assemble): Allow @HA, @L, and @H suffixes on
+ constant expressions.
+
Sun Aug 20 15:54:37 1995 Jim Wilson <wilson@cygnus.com>
* config/tc-arm.c (md_reloc_size): Add const to declaration.
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
index ee03182..c8af6e6 100644
--- a/gas/config/tc-ppc.c
+++ b/gas/config/tc-ppc.c
@@ -16,7 +16,7 @@
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include <ctype.h>
@@ -320,8 +320,8 @@ PowerPC options:\n\
fprintf(stream, "\
-mrelocatable support for GCC's -mrelocatble option\n\
-mlittle, -mlittle-endian\n\
- generate code for a little endian machine\n
--mbig, -mbig-endian generate code for a big endian machine\n
+ generate code for a little endian machine\n\
+-mbig, -mbig-endian generate code for a big endian machine\n\
-V print assembler version number\n\
-Qy, -Qn ignored\n");
#endif
@@ -548,6 +548,16 @@ ppc_elf_suffix (str_p)
*str_p += 2;
return BFD_RELOC_HI16;
}
+ else if (strncmp (str, "@sdarel", 7) == 0 || strncmp (str, "@sdarel", 7) == 0)
+ {
+ *str_p += 7;
+ return BFD_RELOC_GPREL16;
+ }
+ else if (strncmp (str, "@FIXUP", 6) == 0 || strncmp (str, "@fixup", 6) == 0)
+ {
+ *str_p += 6;
+ return BFD_RELOC_CTOR; /* synonym for BFD_RELOC_32 that doesn't get */
+ } /* warnings with -mrelocatable */
return BFD_RELOC_UNUSED;
}
@@ -594,7 +604,9 @@ ppc_elf_cons (nbytes)
demand_empty_rest_of_line ();
}
-/* Validate any relocations emitted for -mrelocatable */
+/* Validate any relocations emitted for -mrelocatable, possibly adding
+ fixups for word relocations in writable segments, so we can adjust
+ them at runtime. */
static void
ppc_elf_validate_fix (fixp, seg)
fixS *fixp;
@@ -607,10 +619,15 @@ ppc_elf_validate_fix (fixp, seg)
&& strcmp (segment_name (seg), ".got2") != 0
&& strcmp (segment_name (seg), ".dtors") != 0
&& strcmp (segment_name (seg), ".ctors") != 0
+ && strcmp (segment_name (seg), ".fixup") != 0
&& strcmp (segment_name (seg), ".stab") != 0)
{
- as_warn_where (fixp->fx_file, fixp->fx_line,
- "Relocation cannot be done when using -mrelocatable");
+ if ((seg->flags & (SEC_READONLY | SEC_CODE)) != 0
+ || fixp->fx_r_type != BFD_RELOC_CTOR)
+ {
+ as_warn_where (fixp->fx_file, fixp->fx_line,
+ "Relocation cannot be done when using -mrelocatable");
+ }
}
}
@@ -779,8 +796,34 @@ md_assemble (str)
else if (ex.X_op == O_absent)
as_bad ("missing operand");
else if (ex.X_op == O_constant)
- insn = ppc_insert_operand (insn, operand, ex.X_add_number,
- (char *) NULL, 0);
+ {
+#ifdef OBJ_ELF
+ /* Allow @HA, @L, @H on constants. */
+ char *orig_str = str;
+ if ((reloc = ppc_elf_suffix (&str)) != BFD_RELOC_UNUSED)
+ switch (reloc)
+ {
+ default:
+ str = orig_str;
+ break;
+
+ case BFD_RELOC_LO16:
+ ex.X_add_number = ((ex.X_add_number & 0xffff) ^ 0x8000) - 0x8000;
+ break;
+
+ case BFD_RELOC_HI16:
+ ex.X_add_number = (ex.X_add_number >> 16) & 0xffff;
+ break;
+
+ case BFD_RELOC_HI16_S:
+ ex.X_add_number = ((ex.X_add_number >> 16) & 0xffff)
+ + ((ex.X_add_number >> 15) & 1);
+ break;
+ }
+#endif
+ insn = ppc_insert_operand (insn, operand, ex.X_add_number,
+ (char *) NULL, 0);
+ }
#ifdef OBJ_ELF
else if ((reloc = ppc_elf_suffix (&str)) != BFD_RELOC_UNUSED)
@@ -858,13 +901,25 @@ md_assemble (str)
reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
int size = (!reloc_howto) ? 0 : bfd_get_reloc_size (reloc_howto);
int offset = target_big_endian ? (4 - size) : 0;
+ fixS *fixP;
if (size > 4)
abort();
- fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,
- &fixups[i].exp, (reloc_howto && reloc_howto->pc_relative),
- fixups[i].reloc);
+ fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,
+ &fixups[i].exp, (reloc_howto && reloc_howto->pc_relative),
+ fixups[i].reloc);
+
+ /* Turn off complaints that the addend is too large for things like
+ foo+100000@ha. */
+ switch (fixups[i].reloc)
+ {
+ case BFD_RELOC_LO16:
+ case BFD_RELOC_HI16:
+ case BFD_RELOC_HI16_S:
+ fixP->fx_no_overflow = 1;
+ break;
+ }
}
else
fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
@@ -2683,6 +2738,7 @@ md_apply_fix3 (fixp, valuep, seg)
switch (fixp->fx_r_type)
{
case BFD_RELOC_32:
+ case BFD_RELOC_CTOR:
if (fixp->fx_pcrel)
{
fixp->fx_r_type = BFD_RELOC_32_PCREL;
@@ -2693,11 +2749,13 @@ md_apply_fix3 (fixp, valuep, seg)
md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
value, 4);
break;
+
case BFD_RELOC_LO16:
case BFD_RELOC_HI16:
case BFD_RELOC_HI16_S:
case BFD_RELOC_PPC_TOC16:
case BFD_RELOC_16:
+ case BFD_RELOC_GPREL16:
if (fixp->fx_pcrel)
abort ();
@@ -2712,6 +2770,7 @@ md_apply_fix3 (fixp, valuep, seg)
md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
value, 1);
break;
+
default:
abort ();
}