+2003-07-09 Alexandre Oliva <aoliva@redhat.com>
+
+ 2003-02-25 Alexandre Oliva <aoliva@redhat.com>
+ * config/tc-mn10300.c (mn10300_check_fixup): Set GOT_PCREL type
+ for subtracts from GLOBAL_OFFSET_TABLE that could not be
+ simplified.
+ 2002-07-18 Alexandre Oliva <aoliva@redhat.com>
+ * config/tc-mn10300.c (mn10300_check_fixup): Accept subtracts that
+ could not be simplified.
+ (tc_gen_reloc): Turn an absolute fx_subsy into part of fx_offset.
+ 2001-11-04 Alexandre Oliva <aoliva@redhat.com>
+ * config/tc-mn10300.h (TC_RELOC_RTSYM_LOC_FIXUP): Don't adjust
+ BDF_RELOC_MN10300_GOT32.
+ * config/tc-mn10300.c (mn10300_fix_adjustable): If
+ TC_RELOC_RTSYM_LOC_FIXUP doesn't hold, it's not adjustable.
+ 2001-05-09 Alexandre Oliva <aoliva@redhat.com>
+ * config/tc-mn10300.c (mn10300_parse_name): Don't return a
+ symbol if we know its value.
+ 2001-05-09 Alexandre Oliva <aoliva@redhat.com>
+ * config/tc-mn10300.h (GLOBAL_OFFSET_TABLE_NAME): Remove
+ duplicate underscore prefix.
+ 2001-05-09 Alexandre Oliva <aoliva@redhat.com>
+ * config/tc-mn10300.c (mn10300_parse_name): Store relocation
+ type in X_md, not X_add_number. Zero X_add_number.
+ (mn10300_check_fixup): Extract relocation type from X_md.
+ * config/tc-mn10300.h: Update comment.
+ 2001-04-14 Alexandre Oliva <aoliva@redhat.com>
+ * config/tc-mn10300.h (O_GOTOFF, O_PLT, O_GOT): Replace with...
+ (O_PIC_reloc): this.
+ * config/tc-mn10300.c (mn10300_PIC_related_p): Use it.
+ (mn10300_check_fixup): Likewise.
+ (mn10300_parse_name): Set X_add_number to relocation type.
+ * config/tc-mn10300.h (DIFF_EXPR_OK, GLOBAL_OFFSET_TABLE_NAME,
+ TC_RELOC_RTSYM_LOC_FIXUP, md_parse_name, TC_CONS_FIX_NEW,
+ O_GOTOFF, O_PLT, O_GOT): Define.
+ * config/tc-mn10300.c (mn10300_PIC_related_p): New fn.
+ (mn10300_check_fixup): New fn.
+ (md_assemble): Call it. Check for PIC-related relocs.
+ (mn10300_cons_fix_new): Likewise. New fn.
+ (mn10300_end_of_match): New fn.
+ (mn10300_md_parse_name_cont): New fn.
+
2003-07-09 Alexandre Oliva <aoliva@redhat.com>
2000-05-25 Alexandre Oliva <aoliva@cygnus.com>
current_machine = MN103;
}
+static symbolS *GOT_symbol;
+
+static inline int mn10300_check_fixup PARAMS ((struct mn10300_fixup *));
+static inline int mn10300_PIC_related_p PARAMS ((symbolS *));
+
+static inline int
+mn10300_PIC_related_p (sym)
+ symbolS *sym;
+{
+ expressionS *exp;
+
+ if (! sym)
+ return 0;
+
+ if (sym == GOT_symbol)
+ return 1;
+
+ exp = symbol_get_value_expression (sym);
+
+ return (exp->X_op == O_PIC_reloc
+ || mn10300_PIC_related_p (exp->X_add_symbol)
+ || mn10300_PIC_related_p (exp->X_op_symbol));
+}
+
+static inline int
+mn10300_check_fixup (fixup)
+ struct mn10300_fixup *fixup;
+{
+ expressionS *exp = &fixup->exp;
+
+ repeat:
+ switch (exp->X_op)
+ {
+ case O_add:
+ case O_subtract: /* If we're sufficiently unlucky that the label
+ and the expression that references it happen
+ to end up in different frags, the subtract
+ won't be simplified within expression(). */
+ /* The PIC-related operand must be the first operand of a sum. */
+ if (exp != &fixup->exp || mn10300_PIC_related_p (exp->X_op_symbol))
+ return 1;
+
+ if (exp->X_add_symbol && exp->X_add_symbol == GOT_symbol)
+ fixup->reloc = BFD_RELOC_32_GOT_PCREL;
+
+ exp = symbol_get_value_expression (exp->X_add_symbol);
+ goto repeat;
+
+ case O_symbol:
+ if (exp->X_add_symbol && exp->X_add_symbol == GOT_symbol)
+ fixup->reloc = BFD_RELOC_32_GOT_PCREL;
+ break;
+
+ case O_PIC_reloc:
+ fixup->reloc = exp->X_md;
+ exp->X_op = O_symbol;
+ if (fixup->reloc == BFD_RELOC_32_PLT_PCREL
+ && fixup->opindex >= 0
+ && (mn10300_operands[fixup->opindex].flags
+ & MN10300_OPERAND_RELAX))
+ return 1;
+ break;
+
+ default:
+ return (mn10300_PIC_related_p (exp->X_add_symbol)
+ || mn10300_PIC_related_p (exp->X_op_symbol));
+ }
+
+ return 0;
+}
+
+void
+mn10300_cons_fix_new (frag, off, size, exp)
+ fragS *frag;
+ int off, size;
+ expressionS *exp;
+{
+ struct mn10300_fixup fixup;
+
+ fixup.opindex = -1;
+ fixup.exp = *exp;
+ fixup.reloc = BFD_RELOC_UNUSED;
+
+ mn10300_check_fixup (&fixup);
+
+ if (fixup.reloc == BFD_RELOC_MN10300_GOT32)
+ switch (size)
+ {
+ case 2:
+ fixup.reloc = BFD_RELOC_MN10300_GOT16;
+ break;
+
+ case 3:
+ fixup.reloc = BFD_RELOC_MN10300_GOT24;
+ break;
+
+ case 4:
+ break;
+
+ default:
+ goto error;
+ }
+ else if (fixup.reloc == BFD_RELOC_UNUSED)
+ switch (size)
+ {
+ case 1:
+ fixup.reloc = BFD_RELOC_8;
+ break;
+
+ case 2:
+ fixup.reloc = BFD_RELOC_16;
+ break;
+
+ case 3:
+ fixup.reloc = BFD_RELOC_24;
+ break;
+
+ case 4:
+ fixup.reloc = BFD_RELOC_32;
+ break;
+
+ default:
+ goto error;
+ }
+ else if (size != 4)
+ {
+ error:
+ as_bad (_("unsupported BFD relocation size %u"), size);
+ fixup.reloc = BFD_RELOC_UNUSED;
+ }
+
+ fix_new_exp (frag, off, size, &fixup.exp, 0, fixup.reloc);
+}
+
void
md_assemble (str)
char *str;
fixups[fc].exp = ex;
fixups[fc].opindex = *opindex_ptr;
fixups[fc].reloc = BFD_RELOC_UNUSED;
+ if (mn10300_check_fixup (& fixups[fc]))
+ goto error;
++fc;
break;
}
const struct mn10300_operand *operand;
operand = &mn10300_operands[fixups[i].opindex];
- if (fixups[i].reloc != BFD_RELOC_UNUSED)
+ if (fixups[i].reloc != BFD_RELOC_UNUSED
+ && fixups[i].reloc != BFD_RELOC_32_GOT_PCREL
+ && fixups[i].reloc != BFD_RELOC_32_GOTOFF
+ && fixups[i].reloc != BFD_RELOC_32_PLT_PCREL
+ && fixups[i].reloc != BFD_RELOC_MN10300_GOT32)
{
reloc_howto_type *reloc_howto;
int size;
fixS *fixP;
reloc = BFD_RELOC_NONE;
+ if (fixups[i].reloc != BFD_RELOC_UNUSED)
+ reloc = fixups[i].reloc;
/* How big is the reloc? Remember SPLIT relocs are
implicitly 32bits. */
if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
/* Is the reloc pc-relative? */
pcrel = (operand->flags & MN10300_OPERAND_PCREL) != 0;
+ if (reloc != BFD_RELOC_NONE)
+ pcrel = bfd_reloc_type_lookup (stdoutput, reloc)->pc_relative;
offset = size - (reloc_size + operand->shift) / 8;
/* Choose a proper BFD relocation type. */
- if (pcrel)
+ if (reloc != BFD_RELOC_NONE)
+ ;
+ else if (pcrel)
{
if (reloc_size == 32)
reloc = BFD_RELOC_32_PCREL;
}
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ if (fixp->fx_subsy
+ && S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
+ {
+ fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
+ fixp->fx_subsy = 0;
+ }
+
if (fixp->fx_addsy && fixp->fx_subsy)
{
reloc->sym_ptr_ptr = NULL;
mn10300_fix_adjustable (fixp)
struct fix *fixp;
{
+ if (! TC_RELOC_RTSYM_LOC_FIXUP (fixp))
+ return 0;
+
if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
return 0;
current_machine = mach;
}
+
+static inline char * mn10300_end_of_match PARAMS ((char *, char *));
+
+static inline char *
+mn10300_end_of_match (cont, what)
+ char *cont, *what;
+{
+ int len = strlen (what);
+
+ if (strncmp (cont, what, strlen (what)) == 0
+ && ! is_part_of_name (cont[len]))
+ return cont + len;
+
+ return NULL;
+}
+
+int
+mn10300_parse_name (name, exprP, nextcharP)
+ char const *name;
+ expressionS *exprP;
+ char *nextcharP;
+{
+ char *next = input_line_pointer;
+ char *next_end;
+ int reloc_type;
+ segT segment;
+
+ exprP->X_op_symbol = NULL;
+
+ if (strcmp (name, GLOBAL_OFFSET_TABLE_NAME) == 0)
+ {
+ if (! GOT_symbol)
+ GOT_symbol = symbol_find_or_make (name);
+
+ exprP->X_add_symbol = GOT_symbol;
+ no_suffix:
+ /* If we have an absolute symbol or a reg,
+ then we know its value now. */
+ segment = S_GET_SEGMENT (exprP->X_add_symbol);
+ if (segment == absolute_section)
+ {
+ exprP->X_op = O_constant;
+ exprP->X_add_number = S_GET_VALUE (exprP->X_add_symbol);
+ exprP->X_add_symbol = NULL;
+ }
+ else if (segment == reg_section)
+ {
+ exprP->X_op = O_register;
+ exprP->X_add_number = S_GET_VALUE (exprP->X_add_symbol);
+ exprP->X_add_symbol = NULL;
+ }
+ else
+ {
+ exprP->X_op = O_symbol;
+ exprP->X_add_number = 0;
+ }
+
+ return 1;
+ }
+
+ exprP->X_add_symbol = symbol_find_or_make (name);
+
+ if (*nextcharP != '@')
+ goto no_suffix;
+ else if ((next_end = mn10300_end_of_match (next + 1, "GOTOFF")))
+ reloc_type = BFD_RELOC_32_GOTOFF;
+ else if ((next_end = mn10300_end_of_match (next + 1, "GOT")))
+ reloc_type = BFD_RELOC_MN10300_GOT32;
+ else if ((next_end = mn10300_end_of_match (next + 1, "PLT")))
+ reloc_type = BFD_RELOC_32_PLT_PCREL;
+ else
+ goto no_suffix;
+
+ *input_line_pointer = *nextcharP;
+ input_line_pointer = next_end;
+ *nextcharP = *input_line_pointer;
+ *input_line_pointer = '\0';
+
+ exprP->X_op = O_PIC_reloc;
+ exprP->X_add_number = 0;
+ exprP->X_md = reloc_type;
+
+ return 1;
+}
#error MN10300 support requires BFD_ASSEMBLER
#endif
+#define DIFF_EXPR_OK
+#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
+
+#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \
+ ((FIX)->fx_r_type != BFD_RELOC_32_PLT_PCREL \
+ && (FIX)->fx_r_type != BFD_RELOC_MN10300_GOT32 \
+ && (FIX)->fx_r_type != BFD_RELOC_32_GOT_PCREL \
+ && ((FIX)->fx_addsy == NULL \
+ || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \
+ && ! S_IS_WEAK ((FIX)->fx_addsy) \
+ && S_IS_DEFINED ((FIX)->fx_addsy) \
+ && ! S_IS_COMMON ((FIX)->fx_addsy))))
+
+#define md_parse_name(name, exprP, nextcharP) \
+ mn10300_parse_name ((name), (exprP), (nextcharP))
+int mn10300_parse_name PARAMS ((char const *, expressionS *, char *));
+
+#define TC_CONS_FIX_NEW(FRAG, OFF, LEN, EXP) \
+ mn10300_cons_fix_new ((FRAG), (OFF), (LEN), (EXP))
+void mn10300_cons_fix_new PARAMS ((fragS *, int, int, expressionS *));
+
+/* This is used to construct expressions out of @GOTOFF, @PLT and @GOT
+ symbols. The relocation type is stored in X_md. */
+#define O_PIC_reloc O_md1
+
/* The target BFD architecture. */
#define TARGET_ARCH bfd_arch_mn10300