if (operand->shift == (int) PPC_OPSHIFT_INV)
{
const char *errmsg;
- int64_t val;
+ uint64_t val;
errmsg = NULL;
val = -1;
data csects. These symbols will not be output. */
ppc_init_xcoff_section (&ppc_xcoff_text_section, text_section, true);
ppc_init_xcoff_section (&ppc_xcoff_data_section, data_section, true);
- ppc_init_xcoff_section (&ppc_xcoff_bss_section, bss_section, false);
+ ppc_init_xcoff_section (&ppc_xcoff_bss_section, bss_section, true);
#endif
}
{
int reloc = ptr->reloc;
- if (!ppc_obj64 && exp_p->X_add_number != 0)
+ if (!ppc_obj64 && (exp_p->X_op == O_big || exp_p->X_add_number != 0))
{
switch (reloc)
{
input_line_pointer = str;
expression (&new_exp);
- if (new_exp.X_op == O_constant)
+ if (new_exp.X_op == O_constant && exp_p->X_op != O_big)
{
exp_p->X_add_number += new_exp.X_add_number;
str = input_line_pointer;
}
-
- if (&input_line_pointer != str_p)
- input_line_pointer = orig_line;
+ input_line_pointer = orig_line;
}
*str_p = str;
}
if (--num_optional_provided < 0)
{
- int64_t val = ppc_optional_operand_value (operand, insn, ppc_cpu,
- num_optional_provided);
+ uint64_t val = ppc_optional_operand_value (operand, insn, ppc_cpu,
+ num_optional_provided);
if (operand->insert)
{
insn = (*operand->insert) (insn, val, ppc_cpu, &errmsg);
insn = ppc_insert_operand (insn, operand, ex.X_add_number,
ppc_cpu, (char *) NULL, 0);
}
- else if (ex.X_op == O_constant)
+ else if (ex.X_op == O_constant
+ || (ex.X_op == O_big && ex.X_add_number > 0))
{
+ uint64_t val;
+ if (ex.X_op == O_constant)
+ {
+ val = ex.X_add_number;
+ if (sizeof (ex.X_add_number) < sizeof (val)
+ && (ex.X_add_number < 0) != ex.X_extrabit)
+ val = val ^ ((addressT) -1 ^ (uint64_t) -1);
+ }
+ else
+ val = generic_bignum_to_int64 ();
#ifdef OBJ_ELF
/* Allow @HA, @L, @H on constants. */
- bfd_reloc_code_real_type reloc;
char *orig_str = str;
+ bfd_reloc_code_real_type reloc = ppc_elf_suffix (&str, &ex);
- if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_NONE)
+ if (ex.X_op == O_constant)
+ {
+ val = ex.X_add_number;
+ if (sizeof (ex.X_add_number) < sizeof (val)
+ && (ex.X_add_number < 0) != ex.X_extrabit)
+ val = val ^ ((addressT) -1 ^ (uint64_t) -1);
+ }
+ if (reloc != BFD_RELOC_NONE)
switch (reloc)
{
default:
break;
case BFD_RELOC_LO16:
- ex.X_add_number &= 0xffff;
+ val &= 0xffff;
if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
- ex.X_add_number = SEX16 (ex.X_add_number);
+ val = SEX16 (val);
break;
case BFD_RELOC_HI16:
if (REPORT_OVERFLOW_HI && ppc_obj64)
{
/* PowerPC64 @h is tested for overflow. */
- ex.X_add_number = (addressT) ex.X_add_number >> 16;
+ val = val >> 16;
if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
{
- addressT sign = (((addressT) -1 >> 16) + 1) >> 1;
- ex.X_add_number
- = ((addressT) ex.X_add_number ^ sign) - sign;
+ uint64_t sign = (((uint64_t) -1 >> 16) + 1) >> 1;
+ val = (val ^ sign) - sign;
}
break;
}
/* Fallthru */
case BFD_RELOC_PPC64_ADDR16_HIGH:
- ex.X_add_number = PPC_HI (ex.X_add_number);
+ val = PPC_HI (val);
if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
- ex.X_add_number = SEX16 (ex.X_add_number);
+ val = SEX16 (val);
break;
case BFD_RELOC_HI16_S:
if (REPORT_OVERFLOW_HI && ppc_obj64)
{
/* PowerPC64 @ha is tested for overflow. */
- ex.X_add_number
- = ((addressT) ex.X_add_number + 0x8000) >> 16;
+ val = (val + 0x8000) >> 16;
if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
{
- addressT sign = (((addressT) -1 >> 16) + 1) >> 1;
- ex.X_add_number
- = ((addressT) ex.X_add_number ^ sign) - sign;
+ uint64_t sign = (((uint64_t) -1 >> 16) + 1) >> 1;
+ val = (val ^ sign) - sign;
}
break;
}
/* Fallthru */
case BFD_RELOC_PPC64_ADDR16_HIGHA:
- ex.X_add_number = PPC_HA (ex.X_add_number);
+ val = PPC_HA (val);
if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
- ex.X_add_number = SEX16 (ex.X_add_number);
+ val = SEX16 (val);
break;
case BFD_RELOC_PPC64_HIGHER:
- ex.X_add_number = PPC_HIGHER (ex.X_add_number);
+ val = PPC_HIGHER (val);
if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
- ex.X_add_number = SEX16 (ex.X_add_number);
+ val = SEX16 (val);
break;
case BFD_RELOC_PPC64_HIGHER_S:
- ex.X_add_number = PPC_HIGHERA (ex.X_add_number);
+ val = PPC_HIGHERA (val);
if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
- ex.X_add_number = SEX16 (ex.X_add_number);
+ val = SEX16 (val);
break;
case BFD_RELOC_PPC64_HIGHEST:
- ex.X_add_number = PPC_HIGHEST (ex.X_add_number);
+ val = PPC_HIGHEST (val);
if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
- ex.X_add_number = SEX16 (ex.X_add_number);
+ val = SEX16 (val);
break;
case BFD_RELOC_PPC64_HIGHEST_S:
- ex.X_add_number = PPC_HIGHESTA (ex.X_add_number);
+ val = PPC_HIGHESTA (val);
if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
- ex.X_add_number = SEX16 (ex.X_add_number);
+ val = SEX16 (val);
break;
}
#endif /* OBJ_ELF */
- insn = ppc_insert_operand (insn, operand, ex.X_add_number,
- ppc_cpu, (char *) NULL, 0);
+ insn = ppc_insert_operand (insn, operand, val, ppc_cpu, NULL, 0);
}
else
{
boundaries. */
frag_align_code (6, 4);
record_alignment (now_seg, 6);
+#ifdef OBJ_XCOFF
+ /* Update alignment of the containing csect. */
+ if (symbol_get_tc (ppc_current_csect)->align < 6)
+ symbol_get_tc (ppc_current_csect)->align = 6;
+#endif
/* Update "dot" in any expressions used by this instruction, and
a label attached to the instruction. By "attached" we mean
flagword oldflags;
const struct xcoff_dwsect_name *dw = &xcoff_dwsect_names[idx];
- sec = subseg_new (dw->name, subseg);
+ sec = subseg_new (dw->xcoff_name, subseg);
oldflags = bfd_section_flags (sec);
if (oldflags == SEC_NO_FLAGS)
{
expression (& exp);
if (*input_line_pointer == ',')
{
- /* The fifth argument is the function size. */
+ /* The fifth argument is the function size.
+ If it's omitted, the size will be the containing csect.
+ This will be donce during ppc_frob_symtab. */
++input_line_pointer;
symbol_get_tc (ext_sym)->u.size
= symbol_new ("L0\001", absolute_section,
/* Discard symbols that should not be included in the output symbol
table. */
if (! symbol_used_in_reloc_p (sym)
+ && S_GET_STORAGE_CLASS (sym) != C_DWARF
&& ((symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM) != 0
|| (! (S_IS_EXTERNAL (sym) || S_IS_WEAK (sym))
&& ! symbol_get_tc (sym)->output
if (SF_GET_FUNCTION (sym))
{
- if (ppc_last_function != (symbolS *) NULL)
- as_bad (_("two .function pseudo-ops with no intervening .ef"));
+ /* Make sure coff_last_function is reset. Otherwise, we won't create
+ the auxent for the next function. */
+ coff_last_function = 0;
ppc_last_function = sym;
if (symbol_get_tc (sym)->u.size != (symbolS *) NULL)
{
SA_SET_SYM_FSIZE (sym,
(long) S_GET_VALUE (symbol_get_tc (sym)->u.size));
}
+ else
+ {
+ /* Size of containing csect. */
+ symbolS* within = symbol_get_tc (sym)->within;
+ union internal_auxent *csectaux;
+ csectaux = &coffsymbol (symbol_get_bfdsym (within))
+ ->native[S_GET_NUMBER_AUXILIARY(within)].u.auxent;
+
+ SA_SET_SYM_FSIZE (sym, csectaux->x_csect.x_scnlen.l);
+ }
}
else if (S_GET_STORAGE_CLASS (sym) == C_FCN
&& strcmp (S_GET_NAME (sym), ".ef") == 0)
a->x_csect.x_scnlen.l = (S_GET_VALUE (symbol_get_tc (sym)->next)
- S_GET_VALUE (sym));
}
- a->x_csect.x_smtyp = (symbol_get_tc (sym)->align << 3) | XTY_SD;
+ if (symbol_get_tc (sym)->symbol_class == XMC_BS)
+ a->x_csect.x_smtyp = (symbol_get_tc (sym)->align << 3) | XTY_CM;
+ else
+ a->x_csect.x_smtyp = (symbol_get_tc (sym)->align << 3) | XTY_SD;
}
else if (S_GET_SEGMENT (sym) == bss_section
|| S_GET_SEGMENT (sym) == ppc_xcoff_tbss_section.segment)
return 0;
}
-/* Adjust the symbol table. This creates csect symbols for all
- absolute symbols. */
+/* Adjust the symbol table. */
void
ppc_adjust_symtab (void)
{
symbolS *sym;
+ symbolS *anchorSym;
+
+ /* Make sure C_DWARF symbols come right after C_FILE.
+ As the C_FILE might not be defined yet and as C_DWARF
+ might already be ordered, we insert them before the
+ first symbol which isn't a C_FILE or a C_DWARF. */
+ for (anchorSym = symbol_rootP; anchorSym != NULL;
+ anchorSym = symbol_next (anchorSym))
+ {
+ if (S_GET_STORAGE_CLASS (anchorSym) != C_FILE
+ && S_GET_STORAGE_CLASS (anchorSym) != C_DWARF)
+ break;
+ }
+
+ sym = anchorSym;
+ while (sym != NULL)
+ {
+ if (S_GET_STORAGE_CLASS (sym) != C_DWARF)
+ {
+ sym = symbol_next (sym);
+ continue;
+ }
+
+ symbolS* tsym = sym;
+ sym = symbol_next (sym);
+
+ symbol_remove (tsym, &symbol_rootP, &symbol_lastP);
+ symbol_insert (tsym, anchorSym, &symbol_rootP, &symbol_lastP);
+ }
+
+ /* Create csect symbols for all absolute symbols. */
if (! ppc_saw_abs)
return;
#ifdef OBJ_XCOFF
+/* Return the surrending csect for sym when possible. */
+
+static symbolS*
+ppc_get_csect_to_adjust (symbolS *sym)
+{
+ if (sym == NULL)
+ return NULL;
+
+ valueT val = resolve_symbol_value (sym);
+ TC_SYMFIELD_TYPE *tc = symbol_get_tc (sym);
+ segT symseg = S_GET_SEGMENT (sym);
+
+ if (tc->subseg == 0
+ && tc->symbol_class != XMC_TC0
+ && tc->symbol_class != XMC_TC
+ && tc->symbol_class != XMC_TE
+ && symseg != bss_section
+ && symseg != ppc_xcoff_tbss_section.segment
+ /* Don't adjust if this is a reloc in the toc section. */
+ && (symseg != data_section
+ || ppc_toc_csect == NULL
+ || val < ppc_toc_frag->fr_address
+ || (ppc_after_toc_frag != NULL
+ && val >= ppc_after_toc_frag->fr_address)))
+ {
+ symbolS* csect = tc->within;
+
+ /* If the symbol was not declared by a label (eg: a section symbol),
+ use the section instead of the csect. This doesn't happen in
+ normal AIX assembly code. */
+ if (csect == NULL)
+ csect = seg_info (symseg)->sym;
+
+ return csect;
+ }
+
+ return NULL;
+}
+
/* This is called to see whether a fixup should be adjusted to use a
section symbol. We take the opportunity to change a fixup against
a symbol in the TOC subsegment into a reloc against the
{
valueT val = resolve_symbol_value (fix->fx_addsy);
segT symseg = S_GET_SEGMENT (fix->fx_addsy);
- TC_SYMFIELD_TYPE *tc;
+ symbolS* csect;
if (symseg == absolute_section)
return 0;
}
/* Possibly adjust the reloc to be against the csect. */
- tc = symbol_get_tc (fix->fx_addsy);
- if (tc->subseg == 0
- && tc->symbol_class != XMC_TC0
- && tc->symbol_class != XMC_TC
- && tc->symbol_class != XMC_TE
- && symseg != bss_section
- && symseg != ppc_xcoff_tbss_section.segment
- /* Don't adjust if this is a reloc in the toc section. */
- && (symseg != data_section
- || ppc_toc_csect == NULL
- || val < ppc_toc_frag->fr_address
- || (ppc_after_toc_frag != NULL
- && val >= ppc_after_toc_frag->fr_address)))
+ if ((csect = ppc_get_csect_to_adjust (fix->fx_addsy)) != NULL)
{
- symbolS *csect = tc->within;
-
- /* If the symbol was not declared by a label (eg: a section symbol),
- use the section instead of the csect. This doesn't happen in
- normal AIX assembly code. */
- if (csect == NULL)
- csect = seg_info (symseg)->sym;
-
fix->fx_offset += val - symbol_get_frag (csect)->fr_address;
fix->fx_addsy = csect;
+ }
- return 0;
+ if ((csect = ppc_get_csect_to_adjust (fix->fx_subsy)) != NULL)
+ {
+ fix->fx_offset -= resolve_symbol_value (fix->fx_subsy)
+ - symbol_get_frag (csect)->fr_address;
+ fix->fx_subsy = csect;
}
/* Adjust a reloc against a .lcomm symbol to be against the base
.lcomm. */
if (symseg == bss_section
- && ! S_IS_EXTERNAL (fix->fx_addsy))
+ && ! S_IS_EXTERNAL (fix->fx_addsy)
+ && symbol_get_tc (fix->fx_addsy)->subseg == 0)
{
symbolS *sy = symbol_get_frag (fix->fx_addsy)->fr_symbol;
symbol_get_bfdsym (fixP->fx_addsy)->flags |= BSF_KEEP;
}
#else
- if (fixP->fx_r_type != BFD_RELOC_PPC_TOC16
- && fixP->fx_r_type != BFD_RELOC_PPC_TOC16_HI
- && fixP->fx_r_type != BFD_RELOC_PPC_TOC16_LO)
- fixP->fx_addnumber = 0;
- else
+ if (fixP->fx_r_type == BFD_RELOC_PPC_TOC16
+ || fixP->fx_r_type == BFD_RELOC_PPC_TOC16_HI
+ || fixP->fx_r_type == BFD_RELOC_PPC_TOC16_LO)
{
/* We want to use the offset within the toc, not the actual VMA
of the symbol. */
/* Set *valP to avoid errors. */
*valP = value;
}
+ else if (fixP->fx_r_type == BFD_RELOC_PPC_TLSM
+ || fixP->fx_r_type == BFD_RELOC_PPC64_TLSM)
+ /* AIX ld expects the section contents for these relocations
+ to be zero. Arrange for that to occur when
+ bfd_install_relocation is called. */
+ fixP->fx_addnumber = (- bfd_section_vma (S_GET_SEGMENT (fixP->fx_addsy))
+ - S_GET_VALUE (fixP->fx_addsy));
+ else
+ fixP->fx_addnumber = 0;
#endif
}
/* Generate a reloc for a fixup. */
-arelent *
+arelent **
tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
{
+ static arelent *relocs[3];
arelent *reloc;
- reloc = XNEW (arelent);
+ relocs[0] = reloc = XNEW (arelent);
+ relocs[1] = NULL;
reloc->sym_ptr_ptr = XNEW (asymbol *);
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
as_bad_where (fixp->fx_file, fixp->fx_line,
_("reloc %d not supported by object file format"),
(int) fixp->fx_r_type);
- return NULL;
+ relocs[0] = NULL;
}
reloc->addend = fixp->fx_addnumber;
- return reloc;
+ if (fixp->fx_subsy && fixp->fx_addsy)
+ {
+ relocs[1] = reloc = XNEW (arelent);
+ relocs[2] = NULL;
+
+ reloc->sym_ptr_ptr = XNEW (asymbol *);
+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_PPC_NEG);
+ reloc->addend = fixp->fx_addnumber;
+
+ if (reloc->howto == (reloc_howto_type *) NULL)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("reloc %d not supported by object file format"),
+ BFD_RELOC_PPC_NEG);
+ relocs[0] = NULL;
+ }
+ }
+
+
+ return relocs;
}
void