+Tue Oct 24 14:50:38 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/tc-ppc.h (TC_FORCE_RELOCATION_SECTION): Rename from
+ TC_FORCE_RELOCATION, taking an additional section argument. If
+ the section of the target symbol is not the same as the current
+ section, always force the relocation to be used.
+ (MD_PCREL_FROM_SECTION): New macro to call md_pcrel_from_section.
+
+ * config/tc-ppc.c (md_pcrel_from_section): Rename from the
+ md_pcrel_from function, taking an additional section argument.
+ Invoke TC_FORCE_RELOCATION_SECTION instead of TC_FORCE_RELOCATION.
+
+ * write.c (TC_FORCE_RELOCATION_SECTION): Define in terms of the
+ older TC_FORCE_RELOCATION if not defined.
+ (MD_PCREL_FROM_SECTION): If not defined, invoke md_pcrel_from.
+ (fixup_segment): Use MD_PCREL_FROM_SECTION instead of
+ md_pcrel_from, and TC_FORCE_RELOCATION_SECTION instead of
+ TC_FORCE_RELOCATION.
+
Mon Oct 23 16:20:04 1995 Ken Raeburn <raeburn@cygnus.com>
* input-scrub.c (as_where): Set name to null pointer if we don't
/* -mpwr means to assemble for the IBM POWER (RIOS1). */
else if (strcmp (arg, "pwr") == 0)
ppc_cpu = PPC_OPCODE_POWER;
- /* -m601 means to assemble for the Motorola PowerPC 601. FIXME: We
- ignore the option for now, but we should really use it to permit
- instructions defined on the 601 that are not part of the standard
- PowerPC architecture (mostly holdovers from the POWER). */
+ /* -m601 means to assemble for the Motorola PowerPC 601, which includes
+ instructions that are holdovers from the Power. */
else if (strcmp (arg, "601") == 0)
ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_601;
/* -mppc, -mppc32, -m603, and -m604 mean to assemble for the
and PowerPC. At present, we just allow the union, rather
than the intersection. */
else if (strcmp (arg, "com") == 0)
- ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_PPC;
+ ppc_cpu = PPC_OPCODE_COMMON;
/* -many means to assemble for any architecture (PWR/PWRX/PPC). */
else if (strcmp (arg, "any") == 0)
- ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_PPC;
+ ppc_cpu = PPC_OPCODE_ANY;
#ifdef OBJ_ELF
/* -mrelocatable/-mrelocatable-lib -- warn about initializations that require relocation */
enum bfd_architecture
ppc_arch ()
{
+ const char *default_cpu = TARGET_CPU;
ppc_set_cpu ();
if ((ppc_cpu & PPC_OPCODE_PPC) != 0)
return bfd_arch_powerpc;
else if ((ppc_cpu & PPC_OPCODE_POWER) != 0)
return bfd_arch_rs6000;
- else
+ else if ((ppc_cpu & (PPC_OPCODE_COMMON | PPC_OPCODE_ANY)) != 0)
{
- as_fatal ("Neither Power nor PowerPC opcodes were selected.");
- return bfd_arch_unknown;
+ if (strcmp (default_cpu, "rs6000") == 0)
+ return bfd_arch_rs6000;
+ else if (strcmp (default_cpu, "powerpc") == 0
+ || strcmp (default_cpu, "powerpcle") == 0)
+ return bfd_arch_powerpc;
}
+
+ as_fatal ("Neither Power nor PowerPC opcodes were selected.");
+ return bfd_arch_unknown;
}
/* This function is called when the assembler starts up. It is called
const struct powerpc_opcode *op_end;
const struct powerpc_macro *macro;
const struct powerpc_macro *macro_end;
+ boolean dup_insn = false;
ppc_set_cpu ();
retval = hash_insert (ppc_hash, op->name, (PTR) op);
if (retval != (const char *) NULL)
{
- /* We permit a duplication of the mfdec instruction on
- the 601, because it seems to have one value on the
- 601 and a different value on other PowerPC
- processors. It's easier to permit a duplication than
- to define a new instruction type flag. When using
- -many/-mcom, the comparison instructions are a harmless
- special case. */
- if (strcmp (retval, "exists") != 0
- || ((((ppc_cpu & PPC_OPCODE_601) == 0
- && ((ppc_cpu & ~PPC_OPCODE_POWER2)
- == (PPC_OPCODE_POWER | PPC_OPCODE_PPC)))
- || strcmp (op->name, "mfdec") != 0)
- && (((ppc_cpu & ~PPC_OPCODE_POWER2)
- != (PPC_OPCODE_POWER | PPC_OPCODE_PPC))
- || (strcmp (op->name, "cmpli") != 0
- && strcmp (op->name, "cmpi") != 0
- && strcmp (op->name, "cmp") != 0
- && strcmp (op->name, "cmpl") != 0))))
- {
- as_bad ("Internal assembler error for instruction %s", op->name);
- abort ();
- }
+ /* Ignore Power duplicates for -m601 */
+ if ((ppc_cpu & PPC_OPCODE_601) != 0
+ && (op->flags & PPC_OPCODE_POWER) != 0)
+ continue;
+
+ as_bad ("Internal assembler error for instruction %s", op->name);
+ dup_insn = true;
}
}
}
retval = hash_insert (ppc_macro_hash, macro->name, (PTR) macro);
if (retval != (const char *) NULL)
- abort ();
+ {
+ as_bad ("Internal assembler error for macro %s", macro->name);
+ dup_insn = true;
+ }
}
}
+ if (dup_insn)
+ abort ();
+
/* Tell the main code what the endianness is if it is not overidden by the user. */
if (!set_target_endian)
{
given a PC relative reloc. */
long
-md_pcrel_from (fixp)
+md_pcrel_from_section (fixp, sec)
fixS *fixp;
+ segT sec;
{
#ifdef OBJ_ELF
if (fixp->fx_addsy != (symbolS *) NULL
&& (! S_IS_DEFINED (fixp->fx_addsy)
- || TC_FORCE_RELOCATION (fixp)))
+ || TC_FORCE_RELOCATION_SECTION (fixp, sec)))
return 0;
#endif
/* Question marks are permitted in symbol names. */
#define LEX_QM 1
+/* Don't adjust TOC relocs. */
+#define tc_fix_adjustable(fixp) ppc_pe_fix_adjustable (fixp)
+extern int ppc_pe_fix_adjustable PARAMS ((struct fix *));
+
#endif
#ifdef OBJ_XCOFF
#endif
/* Branch prediction relocations must force relocation */
-#define TC_FORCE_RELOCATION(FIXP) \
+#define TC_FORCE_RELOCATION_SECTION(FIXP,SEC) \
((FIXP)->fx_r_type == BFD_RELOC_PPC_B16_BRTAKEN \
|| (FIXP)->fx_r_type == BFD_RELOC_PPC_B16_BRNTAKEN \
|| (FIXP)->fx_r_type == BFD_RELOC_PPC_BA16_BRTAKEN \
- || (FIXP)->fx_r_type == BFD_RELOC_PPC_BA16_BRNTAKEN)
+ || (FIXP)->fx_r_type == BFD_RELOC_PPC_BA16_BRNTAKEN \
+ || ((FIXP)->fx_addsy && !(FIXP)->fx_subsy && (FIXP)->fx_addsy->bsym \
+ && (FIXP)->fx_addsy->bsym->section != SEC))
#endif /* OBJ_ELF */
/* call md_apply_fix3 with segment instead of md_apply_fix */
#define MD_APPLY_FIX3
+/* call md_pcrel_from_section, not md_pcrel_from */
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from_section(FIXP, SEC)
+
#define md_operand(x)
#define TC_FORCE_RELOCATION(FIXP) 0
#endif
+#ifndef TC_FORCE_RELOCATION_SECTION
+#define TC_FORCE_RELOCATION_SECTION(FIXP,SEG) TC_FORCE_RELOCATION(FIXP)
+#endif
+
+#ifndef MD_PCREL_FROM_SECTION
+#define MD_PCREL_FROM_SECTION(FIXP, SEC) md_pcrel_from(FIXP)
+#endif
+
#ifndef WORKING_DOT_WORD
extern CONST int md_short_jump_size;
extern CONST int md_long_jump_size;
symbolS *add = NULL;
symbolS *sub = NULL;
offsetT off = 0;
-
+
switch (exp->X_op)
{
case O_absent:
return fix_new_exp (frag, where, size, exp, pcrel, r_type);
}
+ case O_symbol_rva:
+ add = exp->X_add_symbol;
+ off = exp->X_add_number;
+
+#if defined(BFD_ASSEMBLER)
+ r_type = BFD_RELOC_RVA;
+#elif defined(TC_RVA_RELOC)
+ r_type = TC_RVA_RELOC;
+#else
+ as_fatal("rva not supported");
+#endif
+ break;
+
case O_uminus:
sub = exp->X_add_symbol;
off = exp->X_add_number;
{
prev_frag->fr_next = frchp->frch_root;
prev_frag = frchp->frch_last;
+ assert (prev_frag->fr_type != 0);
#ifdef BFD_ASSEMBLER
if (frchp->fix_root != (fixS *) NULL)
{
}
#endif
}
+ assert (prev_frag->fr_type != 0);
prev_frag->fr_next = 0;
return prev_frag;
}
if (sub_symbolP)
{
resolve_symbol_value (sub_symbolP);
- if (!add_symbolP)
+ if (add_symbolP == NULL || add_symbol_segment == absolute_section)
{
- /* Its just -sym */
+ if (add_symbolP != NULL)
+ {
+ add_number += S_GET_VALUE (add_symbolP);
+ add_symbolP = NULL;
+ fixP->fx_addsy = NULL;
+ }
+
+ /* It's just -sym */
if (S_GET_SEGMENT (sub_symbolP) == absolute_section)
- add_number -= S_GET_VALUE (sub_symbolP);
+ {
+ add_number -= S_GET_VALUE (sub_symbolP);
+ fixP->fx_subsy = NULL;
+ }
else if (pcrel
&& S_GET_SEGMENT (sub_symbolP) == this_segment_type)
{
"Negative of non-absolute symbol %s",
S_GET_NAME (sub_symbolP));
}
- else if ((S_GET_SEGMENT (sub_symbolP) == add_symbol_segment)
- && (SEG_NORMAL (add_symbol_segment)
- || (add_symbol_segment == absolute_section)))
+ else if (S_GET_SEGMENT (sub_symbolP) == add_symbol_segment
+ && SEG_NORMAL (add_symbol_segment))
{
/* Difference of 2 symbols from same segment.
Can't make difference of 2 undefineds: 'value' means
/* Let the target machine make the final determination
as to whether or not a relocation will be needed to
handle this fixup. */
- if (!TC_FORCE_RELOCATION (fixP))
+ if (!TC_FORCE_RELOCATION_SECTION (fixP, this_segment_type))
{
fixP->fx_pcrel = 0;
fixP->fx_addsy = NULL;
+ fixP->fx_subsy = NULL;
}
}
else
)
{
/* Make it pc-relative. */
- add_number += (md_pcrel_from (fixP)
+ add_number += (MD_PCREL_FROM_SECTION (fixP, this_segment_type)
- S_GET_VALUE (sub_symbolP));
pcrel = 1;
fixP->fx_pcrel = 1;
#endif /* TC_I960 */
add_number += S_GET_VALUE (add_symbolP);
- add_number -= md_pcrel_from (fixP);
+ add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment_type);
pcrel = 0; /* Lie. Don't want further pcrel processing. */
/* Let the target machine make the final determination
if (pcrel)
{
- add_number -= md_pcrel_from (fixP);
+ add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment_type);
if (add_symbolP == 0)
{
#ifndef BFD_ASSEMBLER