Do not optimize BFD_RELOC_390_GOTENT relocs.

Always generate relocs for VT_ relocs.
This commit is contained in:
Nick Clifton
2001-03-26 19:38:33 +00:00
parent f34754ee25
commit 07855becf9
3 changed files with 948 additions and 777 deletions

View File

@ -1,3 +1,16 @@
2001-03-26 Martin Schwidefsky <schwidefsky@de.ibm.com>
* config/tc-s390.c (tc_s390_fix_adjustable): Add test for
BFD_RELOC_390_GOTENT.
* config/tc-s390.h (TC_RELOC_RTSYM_LOC_FIXUP): Add test for
BFD_RELOC_390_GOTENT.
2001-03-26 Nick Clifton <nickc@redhat.com>
* config/tc-s390.h (TC_FORCE_RELOCATION): Define.
* config/tc-s390.c (s390_force_relocation): New function: Force
relocations for VTINHERIT relocs.
2001-03-23 Stephane Carrez <Stephane.Carrez@worldnet.fr> 2001-03-23 Stephane Carrez <Stephane.Carrez@worldnet.fr>
* doc/as.texinfo: Put @c man begin to generate the as man page. * doc/as.texinfo: Put @c man begin to generate the as man page.

View File

@ -313,13 +313,18 @@ init_default_arch ()
{ {
if (current_arch_requested) if (current_arch_requested)
return; return;
if (strcmp(default_arch, "s390") == 0) {
if (strcmp(default_arch, "s390") == 0)
{
s390_arch_size = 32; s390_arch_size = 32;
current_architecture = S390_OPCODE_ESA; current_architecture = S390_OPCODE_ESA;
} else if (strcmp(default_arch, "s390x") == 0) { }
else if (strcmp(default_arch, "s390x") == 0)
{
s390_arch_size = 64; s390_arch_size = 64;
current_architecture = S390_OPCODE_ESAME; current_architecture = S390_OPCODE_ESAME;
} else }
else
as_fatal ("Invalid default architecture, broken assembler."); as_fatal ("Invalid default architecture, broken assembler.");
current_arch_mask = 1 << current_architecture; current_arch_mask = 1 << current_architecture;
} }
@ -341,7 +346,8 @@ md_parse_option (c, arg)
int c; int c;
char *arg; char *arg;
{ {
switch (c) { switch (c)
{
/* -k: Ignore for FreeBSD compatibility. */ /* -k: Ignore for FreeBSD compatibility. */
case 'k': case 'k':
break; break;
@ -352,20 +358,25 @@ md_parse_option (c, arg)
else if (arg != NULL && strcmp (arg, "no-regnames") == 0) else if (arg != NULL && strcmp (arg, "no-regnames") == 0)
reg_names_p = false; reg_names_p = false;
else { else
{
as_bad (_("invalid switch -m%s"), arg); as_bad (_("invalid switch -m%s"), arg);
return 0; return 0;
} }
break; break;
case 'A': case 'A':
if (arg != NULL && strcmp (arg, "esa") == 0) { if (arg != NULL && strcmp (arg, "esa") == 0)
{
current_architecture = S390_OPCODE_ESA; current_architecture = S390_OPCODE_ESA;
s390_arch_size = 32; s390_arch_size = 32;
} else if (arg != NULL && strcmp (arg, "esame") == 0) { }
else if (arg != NULL && strcmp (arg, "esame") == 0)
{
current_architecture = S390_OPCODE_ESAME; current_architecture = S390_OPCODE_ESAME;
s390_arch_size = 64; s390_arch_size = 64;
} else }
else
as_bad ("invalid architecture -A%s", arg); as_bad ("invalid architecture -A%s", arg);
current_arch_mask = 1 << current_architecture; current_arch_mask = 1 << current_architecture;
current_arch_requested = 1; current_arch_requested = 1;
@ -392,11 +403,11 @@ void
md_show_usage (stream) md_show_usage (stream)
FILE *stream; FILE *stream;
{ {
fprintf(stream, _("\ fprintf (stream, _("\
S390 options:\n\ S390 options:\n\
-mregnames \tAllow symbolic names for registers\n\ -mregnames \tAllow symbolic names for registers\n\
-mno-regnames\tDo not allow symbolic names for registers\n")); -mno-regnames\tDo not allow symbolic names for registers\n"));
fprintf(stream, _("\ fprintf (stream, _("\
-V \tprint assembler version number\n\ -V \tprint assembler version number\n\
-Qy, -Qn \tignored\n")); -Qy, -Qn \tignored\n"));
} }
@ -421,7 +432,8 @@ md_begin ()
s390_opformat_hash = hash_new (); s390_opformat_hash = hash_new ();
op_end = s390_opformats + s390_num_opformats; op_end = s390_opformats + s390_num_opformats;
for (op = s390_opformats; op < op_end; op++) { for (op = s390_opformats; op < op_end; op++)
{
retval = hash_insert (s390_opformat_hash, op->name, (PTR) op); retval = hash_insert (s390_opformat_hash, op->name, (PTR) op);
if (retval != (const char *) NULL) if (retval != (const char *) NULL)
{ {
@ -435,7 +447,8 @@ md_begin ()
s390_opcode_hash = hash_new (); s390_opcode_hash = hash_new ();
op_end = s390_opcodes + s390_num_opcodes; op_end = s390_opcodes + s390_num_opcodes;
for (op = s390_opcodes; op < op_end; op++) { for (op = s390_opcodes; op < op_end; op++)
{
retval = hash_insert (s390_opcode_hash, op->name, (PTR) op); retval = hash_insert (s390_opcode_hash, op->name, (PTR) op);
if (retval != (const char *) NULL) if (retval != (const char *) NULL)
{ {
@ -457,11 +470,10 @@ md_begin ()
void void
s390_md_end () s390_md_end ()
{ {
if (s390_arch_size == 64) { if (s390_arch_size == 64)
bfd_set_arch_mach (stdoutput, bfd_arch_s390, bfd_mach_s390_esame); bfd_set_arch_mach (stdoutput, bfd_arch_s390, bfd_mach_s390_esame);
} else { else
bfd_set_arch_mach (stdoutput, bfd_arch_s390, bfd_mach_s390_esa); bfd_set_arch_mach (stdoutput, bfd_arch_s390, bfd_mach_s390_esa);
}
} }
void void
@ -470,7 +482,8 @@ s390_align_code (fragP, count)
int count; int count;
{ {
/* We use nop pattern 0x0707. */ /* We use nop pattern 0x0707. */
if (count > 0) { if (count > 0)
{
memset(fragP->fr_literal + fragP->fr_fix, 0x07, count); memset(fragP->fr_literal + fragP->fr_fix, 0x07, count);
fragP->fr_var = count; fragP->fr_var = count;
} }
@ -489,7 +502,8 @@ s390_insert_operand (insn, operand, val, file, line)
addressT uval; addressT uval;
int offset; int offset;
if (operand->flags & (S390_OPERAND_SIGNED|S390_OPERAND_PCREL)) { if (operand->flags & (S390_OPERAND_SIGNED|S390_OPERAND_PCREL))
{
offsetT min, max; offsetT min, max;
max = ((offsetT) 1 << (operand->bits - 1)) - 1; max = ((offsetT) 1 << (operand->bits - 1)) - 1;
@ -498,12 +512,14 @@ s390_insert_operand (insn, operand, val, file, line)
if (operand->flags & S390_OPERAND_PCREL) if (operand->flags & S390_OPERAND_PCREL)
val >>= 1; val >>= 1;
/* Check for underflow / overflow. */ /* Check for underflow / overflow. */
if (val < min || val > max) { if (val < min || val > max)
{
const char *err = const char *err =
"operand out of range (%s not between %ld and %ld)"; "operand out of range (%s not between %ld and %ld)";
char buf[100]; char buf[100];
if (operand->flags & S390_OPERAND_PCREL) { if (operand->flags & S390_OPERAND_PCREL)
{
val <<= 1; val <<= 1;
min <<= 1; min <<= 1;
max <<= 1; max <<= 1;
@ -517,7 +533,9 @@ s390_insert_operand (insn, operand, val, file, line)
} }
/* val is ok, now restrict it to operand->bits bits. */ /* val is ok, now restrict it to operand->bits bits. */
uval = (addressT) val & ((((addressT) 1 << (operand->bits-1)) << 1) - 1); uval = (addressT) val & ((((addressT) 1 << (operand->bits-1)) << 1) - 1);
} else { }
else
{
addressT min, max; addressT min, max;
max = (((addressT) 1 << (operand->bits - 1))<<1) - 1; max = (((addressT) 1 << (operand->bits - 1))<<1) - 1;
@ -527,12 +545,14 @@ s390_insert_operand (insn, operand, val, file, line)
if (operand->flags & S390_OPERAND_LENGTH) if (operand->flags & S390_OPERAND_LENGTH)
uval--; uval--;
/* Check for underflow / overflow. */ /* Check for underflow / overflow. */
if (uval < min || uval > max) { if (uval < min || uval > max)
{
const char *err = const char *err =
"operand out of range (%s not between %ld and %ld)"; "operand out of range (%s not between %ld and %ld)";
char buf[100]; char buf[100];
if (operand->flags & S390_OPERAND_LENGTH) { if (operand->flags & S390_OPERAND_LENGTH)
{
uval++; uval++;
min++; min++;
max++; max++;
@ -550,25 +570,29 @@ s390_insert_operand (insn, operand, val, file, line)
offset = operand->shift + operand->bits; offset = operand->shift + operand->bits;
uval <<= (-offset) & 7; uval <<= (-offset) & 7;
insn += (offset - 1)/8; insn += (offset - 1)/8;
while (uval != 0) { while (uval != 0)
{
*insn-- |= uval; *insn-- |= uval;
uval >>= 8; uval >>= 8;
} }
} }
/* Structure used to hold suffixes. */ /* Structure used to hold suffixes. */
typedef enum { typedef enum
{
ELF_SUFFIX_NONE = 0, ELF_SUFFIX_NONE = 0,
ELF_SUFFIX_GOT, ELF_SUFFIX_GOT,
ELF_SUFFIX_PLT, ELF_SUFFIX_PLT,
ELF_SUFFIX_GOTENT ELF_SUFFIX_GOTENT
} elf_suffix_type; }
elf_suffix_type;
struct map_bfd { struct map_bfd
{
char *string; char *string;
int length; int length;
elf_suffix_type suffix; elf_suffix_type suffix;
}; };
/* Parse @got/@plt/@gotoff. and return the desired relocation. */ /* Parse @got/@plt/@gotoff. and return the desired relocation. */
static elf_suffix_type static elf_suffix_type
@ -576,7 +600,8 @@ s390_elf_suffix (str_p, exp_p)
char **str_p; char **str_p;
expressionS *exp_p; expressionS *exp_p;
{ {
static struct map_bfd mapping[] = { static struct map_bfd mapping[] =
{
{ "got", 3, ELF_SUFFIX_GOT }, { "got", 3, ELF_SUFFIX_GOT },
{ "got12", 5, ELF_SUFFIX_GOT }, { "got12", 5, ELF_SUFFIX_GOT },
{ "plt", 3, ELF_SUFFIX_PLT }, { "plt", 3, ELF_SUFFIX_PLT },
@ -599,19 +624,22 @@ s390_elf_suffix (str_p, exp_p)
for (ptr = &mapping[0]; ptr->length > 0; ptr++) for (ptr = &mapping[0]; ptr->length > 0; ptr++)
if (len == ptr->length && if (len == ptr->length &&
strncasecmp(ident, ptr->string, ptr->length) == 0) { strncasecmp(ident, ptr->string, ptr->length) == 0)
{
if (exp_p->X_add_number != 0) if (exp_p->X_add_number != 0)
as_warn (_("identifier+constant@%s means identifier@%s+constant"), as_warn (_("identifier+constant@%s means identifier@%s+constant"),
ptr->string, ptr->string); ptr->string, ptr->string);
/* Now check for identifier@suffix+constant. */ /* Now check for identifier@suffix+constant. */
if (*str == '-' || *str == '+') { if (*str == '-' || *str == '+')
{
char *orig_line = input_line_pointer; char *orig_line = input_line_pointer;
expressionS new_exp; expressionS new_exp;
input_line_pointer = str; input_line_pointer = str;
expression (&new_exp); expression (&new_exp);
switch (new_exp.X_op) { switch (new_exp.X_op)
{
case O_constant: /* X_add_number (a constant expression). */ case O_constant: /* X_add_number (a constant expression). */
exp_p->X_add_number += new_exp.X_add_number; exp_p->X_add_number += new_exp.X_add_number;
str = input_line_pointer; str = input_line_pointer;
@ -649,7 +677,8 @@ s390_elf_suffix (str_p, exp_p)
} }
/* Structure used to hold a literal pool entry. */ /* Structure used to hold a literal pool entry. */
struct s390_lpe { struct s390_lpe
{
struct s390_lpe *next; struct s390_lpe *next;
expressionS ex; expressionS ex;
FLONUM_TYPE floatnum; /* used if X_op == O_big && X_add_number <= 0 */ FLONUM_TYPE floatnum; /* used if X_op == O_big && X_add_number <= 0 */
@ -657,7 +686,7 @@ struct s390_lpe {
int nbytes; int nbytes;
bfd_reloc_code_real_type reloc; bfd_reloc_code_real_type reloc;
symbolS *sym; symbolS *sym;
}; };
static struct s390_lpe *lpe_free_list = NULL; static struct s390_lpe *lpe_free_list = NULL;
static struct s390_lpe *lpe_list = NULL; static struct s390_lpe *lpe_list = NULL;
@ -674,7 +703,8 @@ s390_exp_compare(exp1, exp2)
if (exp1->X_op != exp2->X_op) if (exp1->X_op != exp2->X_op)
return 0; return 0;
switch (exp1->X_op) { switch (exp1->X_op)
{
case O_constant: /* X_add_number must be equal. */ case O_constant: /* X_add_number must be equal. */
case O_register: case O_register:
return exp1->X_add_number == exp2->X_add_number; return exp1->X_add_number == exp2->X_add_number;
@ -746,81 +776,106 @@ s390_lit_suffix (str_p, exp_p, suffix)
nbytes = ident[3] - '0'; nbytes = ident[3] - '0';
reloc = BFD_RELOC_UNUSED; reloc = BFD_RELOC_UNUSED;
if (suffix == ELF_SUFFIX_GOT) { if (suffix == ELF_SUFFIX_GOT)
{
if (nbytes == 2) if (nbytes == 2)
reloc = BFD_RELOC_390_GOT16; reloc = BFD_RELOC_390_GOT16;
else if (nbytes == 4) else if (nbytes == 4)
reloc = BFD_RELOC_32_GOT_PCREL; reloc = BFD_RELOC_32_GOT_PCREL;
else if (nbytes == 8) else if (nbytes == 8)
reloc = BFD_RELOC_390_GOT64; reloc = BFD_RELOC_390_GOT64;
} else if (suffix == ELF_SUFFIX_PLT) { }
else if (suffix == ELF_SUFFIX_PLT)
{
if (nbytes == 4) if (nbytes == 4)
reloc = BFD_RELOC_390_PLT32; reloc = BFD_RELOC_390_PLT32;
else if (nbytes == 8) else if (nbytes == 8)
reloc = BFD_RELOC_390_PLT64; reloc = BFD_RELOC_390_PLT64;
} }
if (suffix != ELF_SUFFIX_NONE && reloc == BFD_RELOC_UNUSED) { if (suffix != ELF_SUFFIX_NONE && reloc == BFD_RELOC_UNUSED)
as_bad (_("Invalid suffix for literal pool entry")); as_bad (_("Invalid suffix for literal pool entry"));
}
/* Search the pool if the new entry is a duplicate. */ /* Search the pool if the new entry is a duplicate. */
if (exp_p->X_op == O_big) { if (exp_p->X_op == O_big)
{
/* Special processing for big numbers. */ /* Special processing for big numbers. */
for (lpe = lpe_list; lpe != NULL; lpe = lpe->next) { for (lpe = lpe_list; lpe != NULL; lpe = lpe->next)
if (lpe->ex.X_op == O_big) { {
if (exp_p->X_add_number <= 0 && lpe->ex.X_add_number <= 0) { if (lpe->ex.X_op == O_big)
if (memcmp(&generic_floating_point_number, &lpe->floatnum, {
sizeof(FLONUM_TYPE)) == 0) if (exp_p->X_add_number <= 0 && lpe->ex.X_add_number <= 0)
{
if (memcmp (&generic_floating_point_number, &lpe->floatnum,
sizeof (FLONUM_TYPE)) == 0)
break; break;
} else if (exp_p->X_add_number == lpe->ex.X_add_number) { }
if (memcmp(generic_bignum, lpe->bignum, else if (exp_p->X_add_number == lpe->ex.X_add_number)
sizeof(LITTLENUM_TYPE)*exp_p->X_add_number) == 0) {
if (memcmp (generic_bignum, lpe->bignum,
sizeof (LITTLENUM_TYPE)*exp_p->X_add_number) == 0)
break; break;
} }
} }
} }
} else { }
else
{
/* Processing for 'normal' data types. */ /* Processing for 'normal' data types. */
for (lpe = lpe_list; lpe != NULL; lpe = lpe->next) for (lpe = lpe_list; lpe != NULL; lpe = lpe->next)
if (lpe->nbytes == nbytes && lpe->reloc == reloc && if (lpe->nbytes == nbytes && lpe->reloc == reloc &&
s390_exp_compare(exp_p, &lpe->ex) != 0) s390_exp_compare(exp_p, &lpe->ex) != 0)
break; break;
} }
if (lpe == NULL) { /* A new literal. */
if (lpe_free_list != NULL) { if (lpe == NULL)
{
/* A new literal. */
if (lpe_free_list != NULL)
{
lpe = lpe_free_list; lpe = lpe_free_list;
lpe_free_list = lpe_free_list->next; lpe_free_list = lpe_free_list->next;
} else { }
else
{
lpe = (struct s390_lpe *) xmalloc(sizeof(struct s390_lpe)); lpe = (struct s390_lpe *) xmalloc(sizeof(struct s390_lpe));
} }
lpe->ex = *exp_p; lpe->ex = *exp_p;
if (exp_p->X_op == O_big) {
if (exp_p->X_op == O_big)
{
if (exp_p->X_add_number <= 0) if (exp_p->X_add_number <= 0)
lpe->floatnum = generic_floating_point_number; lpe->floatnum = generic_floating_point_number;
else if (exp_p->X_add_number <= 4) else if (exp_p->X_add_number <= 4)
memcpy(lpe->bignum, generic_bignum, memcpy (lpe->bignum, generic_bignum,
exp_p->X_add_number*sizeof(LITTLENUM_TYPE)); exp_p->X_add_number*sizeof(LITTLENUM_TYPE));
else else
as_bad(_("Big number is too big")); as_bad (_("Big number is too big"));
} }
lpe->nbytes = nbytes; lpe->nbytes = nbytes;
lpe->reloc = reloc; lpe->reloc = reloc;
/* Literal pool name defined ? */ /* Literal pool name defined ? */
if (lp_sym == NULL) { if (lp_sym == NULL)
{
sprintf(tmp_name, ".L\001%i", lp_count); sprintf(tmp_name, ".L\001%i", lp_count);
lp_sym = symbol_make(tmp_name); lp_sym = symbol_make(tmp_name);
} }
/* Make name for literal pool entry. */ /* Make name for literal pool entry. */
sprintf(tmp_name, ".L\001%i\002%i", lp_count, lpe_count); sprintf(tmp_name, ".L\001%i\002%i", lp_count, lpe_count);
lpe_count++; lpe_count++;
lpe->sym = symbol_make(tmp_name); lpe->sym = symbol_make(tmp_name);
/* Add to literal pool list. */ /* Add to literal pool list. */
lpe->next = NULL; lpe->next = NULL;
if (lpe_list_tail != NULL) { if (lpe_list_tail != NULL)
{
lpe_list_tail->next = lpe; lpe_list_tail->next = lpe;
lpe_list_tail = lpe; lpe_list_tail = lpe;
} else }
else
lpe_list = lpe_list_tail = lpe; lpe_list = lpe_list_tail = lpe;
} }
@ -847,15 +902,20 @@ s390_elf_cons (nbytes)
expressionS exp; expressionS exp;
elf_suffix_type suffix; elf_suffix_type suffix;
if (is_it_end_of_statement ()) { if (is_it_end_of_statement ())
{
demand_empty_rest_of_line (); demand_empty_rest_of_line ();
return; return;
} }
do { do
{
expression (&exp); expression (&exp);
if (exp.X_op == O_symbol && *input_line_pointer == '@' &&
(suffix=s390_elf_suffix(&input_line_pointer, &exp))!=ELF_SUFFIX_NONE) { if (exp.X_op == O_symbol
&& *input_line_pointer == '@'
&& (suffix = s390_elf_suffix (&input_line_pointer, &exp)) != ELF_SUFFIX_NONE)
{
bfd_reloc_code_real_type reloc; bfd_reloc_code_real_type reloc;
reloc_howto_type *reloc_howto; reloc_howto_type *reloc_howto;
int size; int size;
@ -874,7 +934,8 @@ s390_elf_cons (nbytes)
else else
reloc = BFD_RELOC_UNUSED; reloc = BFD_RELOC_UNUSED;
if (reloc != BFD_RELOC_UNUSED) { if (reloc != BFD_RELOC_UNUSED)
{
reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc); reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc);
size = bfd_get_reloc_size (reloc_howto); size = bfd_get_reloc_size (reloc_howto);
if (size > nbytes) if (size > nbytes)
@ -884,11 +945,14 @@ s390_elf_cons (nbytes)
md_number_to_chars (where, 0, size); md_number_to_chars (where, 0, size);
fix_new_exp (frag_now, where - frag_now->fr_literal, fix_new_exp (frag_now, where - frag_now->fr_literal,
size, &exp, reloc_howto->pc_relative, reloc); size, &exp, reloc_howto->pc_relative, reloc);
} else }
else
as_bad (_("relocation not applicable")); as_bad (_("relocation not applicable"));
} else }
else
emit_expr (&exp, (unsigned int) nbytes); emit_expr (&exp, (unsigned int) nbytes);
} while (*input_line_pointer++ == ','); }
while (*input_line_pointer++ == ',');
input_line_pointer--; /* Put terminator back into stream. */ input_line_pointer--; /* Put terminator back into stream. */
demand_empty_rest_of_line (); demand_empty_rest_of_line ();
@ -899,11 +963,11 @@ s390_elf_cons (nbytes)
that would screw up references to ``.''. */ that would screw up references to ``.''. */
struct s390_fixup struct s390_fixup
{ {
expressionS exp; expressionS exp;
int opindex; int opindex;
bfd_reloc_code_real_type reloc; bfd_reloc_code_real_type reloc;
}; };
#define MAX_INSN_FIXUPS (4) #define MAX_INSN_FIXUPS (4)
@ -932,13 +996,15 @@ md_gather_operands (str, insn, opcode)
/* Gather the operands. */ /* Gather the operands. */
fc = 0; fc = 0;
for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++) { for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
{
expressionS ex; expressionS ex;
char *hold; char *hold;
operand = s390_operands + *opindex_ptr; operand = s390_operands + *opindex_ptr;
if (skip_optional && (operand->flags & S390_OPERAND_INDEX)) { if (skip_optional && (operand->flags & S390_OPERAND_INDEX))
{
/* We do an early skip. For D(X,B) constructions the index /* We do an early skip. For D(X,B) constructions the index
register is skipped (X is optional). For D(L,B) the base register is skipped (X is optional). For D(L,B) the base
register will be the skipped operand, because L is NOT register will be the skipped operand, because L is NOT
@ -962,9 +1028,12 @@ md_gather_operands (str, insn, opcode)
as_bad (_("illegal operand")); as_bad (_("illegal operand"));
else if (ex.X_op == O_absent) else if (ex.X_op == O_absent)
as_bad (_("missing operand")); as_bad (_("missing operand"));
else if (ex.X_op == O_register || ex.X_op == O_constant) { else if (ex.X_op == O_register || ex.X_op == O_constant)
{
s390_lit_suffix (&str, &ex, ELF_SUFFIX_NONE); s390_lit_suffix (&str, &ex, ELF_SUFFIX_NONE);
if (ex.X_op != O_register && ex.X_op != O_constant) {
if (ex.X_op != O_register && ex.X_op != O_constant)
{
/* We need to generate a fixup for the /* We need to generate a fixup for the
expression returned by s390_lit_suffix. */ expression returned by s390_lit_suffix. */
if (fc >= MAX_INSN_FIXUPS) if (fc >= MAX_INSN_FIXUPS)
@ -973,18 +1042,24 @@ md_gather_operands (str, insn, opcode)
fixups[fc].opindex = *opindex_ptr; fixups[fc].opindex = *opindex_ptr;
fixups[fc].reloc = BFD_RELOC_UNUSED; fixups[fc].reloc = BFD_RELOC_UNUSED;
++fc; ++fc;
} else { }
else
{
if ((operand->flags & S390_OPERAND_INDEX) && ex.X_add_number == 0) if ((operand->flags & S390_OPERAND_INDEX) && ex.X_add_number == 0)
as_warn("index register specified but zero"); as_warn("index register specified but zero");
if ((operand->flags & S390_OPERAND_BASE) && ex.X_add_number == 0) if ((operand->flags & S390_OPERAND_BASE) && ex.X_add_number == 0)
as_warn("base register specified but zero"); as_warn("base register specified but zero");
s390_insert_operand (insn, operand, ex.X_add_number, NULL, 0); s390_insert_operand (insn, operand, ex.X_add_number, NULL, 0);
} }
} else { }
else
{
suffix = s390_elf_suffix (&str, &ex); suffix = s390_elf_suffix (&str, &ex);
suffix = s390_lit_suffix (&str, &ex, suffix); suffix = s390_lit_suffix (&str, &ex, suffix);
reloc = BFD_RELOC_UNUSED; reloc = BFD_RELOC_UNUSED;
if (suffix == ELF_SUFFIX_GOT) {
if (suffix == ELF_SUFFIX_GOT)
{
if (operand->flags & S390_OPERAND_DISP) if (operand->flags & S390_OPERAND_DISP)
reloc = BFD_RELOC_390_GOT12; reloc = BFD_RELOC_390_GOT12;
else if ((operand->flags & S390_OPERAND_SIGNED) && else if ((operand->flags & S390_OPERAND_SIGNED) &&
@ -993,14 +1068,18 @@ md_gather_operands (str, insn, opcode)
else if ((operand->flags & S390_OPERAND_PCREL) && else if ((operand->flags & S390_OPERAND_PCREL) &&
(operand->bits == 32)) (operand->bits == 32))
reloc = BFD_RELOC_390_GOTENT; reloc = BFD_RELOC_390_GOTENT;
} else if (suffix == ELF_SUFFIX_PLT) { }
else if (suffix == ELF_SUFFIX_PLT)
{
if ((operand->flags & S390_OPERAND_PCREL) && if ((operand->flags & S390_OPERAND_PCREL) &&
(operand->bits == 16)) (operand->bits == 16))
reloc = BFD_RELOC_390_PLT16DBL; reloc = BFD_RELOC_390_PLT16DBL;
else if ((operand->flags & S390_OPERAND_PCREL) && else if ((operand->flags & S390_OPERAND_PCREL) &&
(operand->bits == 32)) (operand->bits == 32))
reloc = BFD_RELOC_390_PLT32DBL; reloc = BFD_RELOC_390_PLT32DBL;
} else if (suffix == ELF_SUFFIX_GOTENT) { }
else if (suffix == ELF_SUFFIX_GOTENT)
{
if ((operand->flags & S390_OPERAND_PCREL) && if ((operand->flags & S390_OPERAND_PCREL) &&
(operand->bits == 32)) (operand->bits == 32))
reloc = BFD_RELOC_390_GOTENT; reloc = BFD_RELOC_390_GOTENT;
@ -1020,9 +1099,11 @@ md_gather_operands (str, insn, opcode)
/* Check the next character. The call to expression has advanced /* Check the next character. The call to expression has advanced
str past any whitespace. */ str past any whitespace. */
if (operand->flags & S390_OPERAND_DISP) { if (operand->flags & S390_OPERAND_DISP)
{
/* After a displacement a block in parentheses can start. */ /* After a displacement a block in parentheses can start. */
if (*str != '(') { if (*str != '(')
{
/* Check if parethesed block can be skipped. If the next /* Check if parethesed block can be skipped. If the next
operand is neiter an optional operand nor a base register operand is neiter an optional operand nor a base register
then we have a syntax error. */ then we have a syntax error. */
@ -1035,11 +1116,15 @@ md_gather_operands (str, insn, opcode)
operand = s390_operands + *(++opindex_ptr); operand = s390_operands + *(++opindex_ptr);
/* If there is a next operand it must be seperated by a comma. */ /* If there is a next operand it must be seperated by a comma. */
if (opindex_ptr[1] != '\0') { if (opindex_ptr[1] != '\0')
{
if (*str++ != ',') if (*str++ != ',')
as_bad(_("syntax error; expected ,")); as_bad(_("syntax error; expected ,"));
} }
} else { /* We found an opening parentheses. */ }
else
{
/* We found an opening parentheses. */
str++; str++;
for (f = str; *f != '\0'; f++) for (f = str; *f != '\0'; f++)
if (*f == ',' || *f == ')') if (*f == ',' || *f == ')')
@ -1047,33 +1132,44 @@ md_gather_operands (str, insn, opcode)
/* If there is no comma until the closing parentheses OR /* If there is no comma until the closing parentheses OR
there is a comma right after the opening parentheses, there is a comma right after the opening parentheses,
we have to skip optional operands. */ we have to skip optional operands. */
if (*f == ',' && f == str) { /* comma directly after '(' ? */ if (*f == ',' && f == str)
{
/* comma directly after '(' ? */
skip_optional = 1; skip_optional = 1;
str++; str++;
} else }
else
skip_optional = (*f != ','); skip_optional = (*f != ',');
} }
} else if (operand->flags & S390_OPERAND_BASE) { }
else if (operand->flags & S390_OPERAND_BASE)
{
/* After the base register the parenthesed block ends. */ /* After the base register the parenthesed block ends. */
if (*str++ != ')') if (*str++ != ')')
as_bad(_("syntax error; missing ')' after base register")); as_bad (_("syntax error; missing ')' after base register"));
skip_optional = 0; skip_optional = 0;
/* If there is a next operand it must be seperated by a comma. */ /* If there is a next operand it must be seperated by a comma. */
if (opindex_ptr[1] != '\0') { if (opindex_ptr[1] != '\0')
{
if (*str++ != ',') if (*str++ != ',')
as_bad(_("syntax error; expected ,")); as_bad (_("syntax error; expected ,"));
} }
} else { }
else
{
/* We can find an 'early' closing parentheses in e.g. D(L) instead /* We can find an 'early' closing parentheses in e.g. D(L) instead
of D(L,B). In this case the base register has to be skipped. */ of D(L,B). In this case the base register has to be skipped. */
if (*str == ')') { if (*str == ')')
{
operand = s390_operands + *(++opindex_ptr); operand = s390_operands + *(++opindex_ptr);
if (!(operand->flags & S390_OPERAND_BASE)) if (!(operand->flags & S390_OPERAND_BASE))
as_bad (_("syntax error; ')' not allowed here")); as_bad (_("syntax error; ')' not allowed here"));
str++; str++;
} }
/* If there is a next operand it must be seperated by a comma. */ /* If there is a next operand it must be seperated by a comma. */
if (opindex_ptr[1] != '\0') { if (opindex_ptr[1] != '\0')
{
if (*str++ != ',') if (*str++ != ',')
as_bad(_("syntax error; expected ,")); as_bad(_("syntax error; expected ,"));
} }
@ -1083,7 +1179,8 @@ md_gather_operands (str, insn, opcode)
while (isspace (*str)) while (isspace (*str))
++str; ++str;
if (*str != '\0') { if (*str != '\0')
{
char *linefeed; char *linefeed;
if ((linefeed = strchr(str, '\n')) != NULL) if ((linefeed = strchr(str, '\n')) != NULL)
@ -1095,7 +1192,7 @@ md_gather_operands (str, insn, opcode)
/* Write out the instruction. */ /* Write out the instruction. */
f = frag_more (opcode->oplen); f = frag_more (opcode->oplen);
memcpy(f, insn, opcode->oplen); memcpy (f, insn, opcode->oplen);
/* Create any fixups. At this point we do not use a /* Create any fixups. At this point we do not use a
bfd_reloc_code_real_type, but instead just use the bfd_reloc_code_real_type, but instead just use the
@ -1103,10 +1200,12 @@ md_gather_operands (str, insn, opcode)
handle fixups for any operand type, although that is admittedly handle fixups for any operand type, although that is admittedly
not a very exciting feature. We pick a BFD reloc type in not a very exciting feature. We pick a BFD reloc type in
md_apply_fix3. */ md_apply_fix3. */
for (i = 0; i < fc; i++) { for (i = 0; i < fc; i++)
{
operand = s390_operands + fixups[i].opindex; operand = s390_operands + fixups[i].opindex;
if (fixups[i].reloc != BFD_RELOC_UNUSED) { if (fixups[i].reloc != BFD_RELOC_UNUSED)
{
reloc_howto_type *reloc_howto; reloc_howto_type *reloc_howto;
fixS *fixP; fixS *fixP;
int size; int size;
@ -1118,7 +1217,7 @@ md_gather_operands (str, insn, opcode)
size = bfd_get_reloc_size (reloc_howto); size = bfd_get_reloc_size (reloc_howto);
if (size < 1 || size > 4) if (size < 1 || size > 4)
abort(); abort ();
fixP = fix_new_exp (frag_now, fixP = fix_new_exp (frag_now,
f - frag_now->fr_literal + (operand->shift/8), f - frag_now->fr_literal + (operand->shift/8),
@ -1130,7 +1229,8 @@ md_gather_operands (str, insn, opcode)
if (fixups[i].reloc == BFD_RELOC_390_GOT12 || if (fixups[i].reloc == BFD_RELOC_390_GOT12 ||
fixups[i].reloc == BFD_RELOC_390_GOT16) fixups[i].reloc == BFD_RELOC_390_GOT16)
fixP->fx_no_overflow = 1; fixP->fx_no_overflow = 1;
} else }
else
fix_new_exp (frag_now, f - frag_now->fr_literal, 4, &fixups[i].exp, fix_new_exp (frag_now, f - frag_now->fr_literal, 4, &fixups[i].exp,
(operand->flags & S390_OPERAND_PCREL) != 0, (operand->flags & S390_OPERAND_PCREL) != 0,
((bfd_reloc_code_real_type) ((bfd_reloc_code_real_type)
@ -1157,16 +1257,19 @@ md_assemble (str)
/* Look up the opcode in the hash table. */ /* Look up the opcode in the hash table. */
opcode = (struct s390_opcode *) hash_find (s390_opcode_hash, str); opcode = (struct s390_opcode *) hash_find (s390_opcode_hash, str);
if (opcode == (const struct s390_opcode *) NULL) { if (opcode == (const struct s390_opcode *) NULL)
{
as_bad (_("Unrecognized opcode: `%s'"), str); as_bad (_("Unrecognized opcode: `%s'"), str);
return; return;
} else if (!(opcode->architecture & current_arch_mask)) { }
else if (!(opcode->architecture & current_arch_mask))
{
as_bad("Opcode %s not available in this architecture", str); as_bad("Opcode %s not available in this architecture", str);
return; return;
} }
memcpy(insn, opcode->opcode, sizeof(insn)); memcpy (insn, opcode->opcode, sizeof(insn));
md_gather_operands(s, insn, opcode); md_gather_operands (s, insn, opcode);
} }
#ifndef WORKING_DOT_WORD #ifndef WORKING_DOT_WORD
@ -1225,28 +1328,35 @@ s390_insn(ignore)
/* Look up the opcode in the hash table. */ /* Look up the opcode in the hash table. */
opformat = (struct s390_opcode *) opformat = (struct s390_opcode *)
hash_find (s390_opformat_hash, input_line_pointer); hash_find (s390_opformat_hash, input_line_pointer);
if (opformat == (const struct s390_opcode *) NULL) { if (opformat == (const struct s390_opcode *) NULL)
{
as_bad (_("Unrecognized opcode format: `%s'"), input_line_pointer); as_bad (_("Unrecognized opcode format: `%s'"), input_line_pointer);
return; return;
} }
input_line_pointer = s; input_line_pointer = s;
expression (&exp); expression (&exp);
if (exp.X_op == O_constant) { if (exp.X_op == O_constant)
{
if (opformat->oplen == 4 || if (opformat->oplen == 4 ||
(opformat->oplen == 2 && exp.X_op < 0x10000)) (opformat->oplen == 2 && exp.X_op < 0x10000))
md_number_to_chars (insn, exp.X_add_number, opformat->oplen); md_number_to_chars (insn, exp.X_add_number, opformat->oplen);
else else
as_bad(_("Invalid .insn format\n")); as_bad(_("Invalid .insn format\n"));
} else if (exp.X_op == O_big) { }
else if (exp.X_op == O_big)
{
if (exp.X_add_number > 0 && if (exp.X_add_number > 0 &&
opformat->oplen == 6 && opformat->oplen == 6 &&
generic_bignum[3] == 0) { generic_bignum[3] == 0)
{
md_number_to_chars (insn, generic_bignum[2], 2); md_number_to_chars (insn, generic_bignum[2], 2);
md_number_to_chars (&insn[2], generic_bignum[1], 2); md_number_to_chars (&insn[2], generic_bignum[1], 2);
md_number_to_chars (&insn[4], generic_bignum[0], 2); md_number_to_chars (&insn[4], generic_bignum[0], 2);
} else }
else
as_bad(_("Invalid .insn format\n")); as_bad(_("Invalid .insn format\n"));
} else }
else
as_bad (_("second operand of .insn not a constant\n")); as_bad (_("second operand of .insn not a constant\n"));
if (*input_line_pointer++ != ',') if (*input_line_pointer++ != ',')
as_bad (_("missing comma after insn constant\n")); as_bad (_("missing comma after insn constant\n"));
@ -1312,7 +1422,8 @@ s390_literals (ignore)
S_SET_VALUE (lp_sym, (valueT) frag_now_fix ()); S_SET_VALUE (lp_sym, (valueT) frag_now_fix ());
lp_sym->sy_frag = frag_now; lp_sym->sy_frag = frag_now;
while (lpe_list) { while (lpe_list)
{
lpe = lpe_list; lpe = lpe_list;
lpe_list = lpe_list->next; lpe_list = lpe_list->next;
S_SET_SEGMENT (lpe->sym, now_seg); S_SET_SEGMENT (lpe->sym, now_seg);
@ -1320,7 +1431,8 @@ s390_literals (ignore)
lpe->sym->sy_frag = frag_now; lpe->sym->sy_frag = frag_now;
/* Emit literal pool entry. */ /* Emit literal pool entry. */
if (lpe->reloc != BFD_RELOC_UNUSED) { if (lpe->reloc != BFD_RELOC_UNUSED)
{
reloc_howto_type *reloc_howto = reloc_howto_type *reloc_howto =
bfd_reloc_type_lookup (stdoutput, lpe->reloc); bfd_reloc_type_lookup (stdoutput, lpe->reloc);
int size = bfd_get_reloc_size (reloc_howto); int size = bfd_get_reloc_size (reloc_howto);
@ -1333,12 +1445,15 @@ s390_literals (ignore)
md_number_to_chars (where, 0, size); md_number_to_chars (where, 0, size);
fix_new_exp (frag_now, where - frag_now->fr_literal, fix_new_exp (frag_now, where - frag_now->fr_literal,
size, &lpe->ex, reloc_howto->pc_relative, lpe->reloc); size, &lpe->ex, reloc_howto->pc_relative, lpe->reloc);
} else { }
if (lpe->ex.X_op == O_big) { else
{
if (lpe->ex.X_op == O_big)
{
if (lpe->ex.X_add_number <= 0) if (lpe->ex.X_add_number <= 0)
generic_floating_point_number = lpe->floatnum; generic_floating_point_number = lpe->floatnum;
else else
memcpy(generic_bignum, lpe->bignum, memcpy (generic_bignum, lpe->bignum,
lpe->ex.X_add_number*sizeof(LITTLENUM_TYPE)); lpe->ex.X_add_number*sizeof(LITTLENUM_TYPE));
} }
emit_expr (&lpe->ex, lpe->nbytes); emit_expr (&lpe->ex, lpe->nbytes);
@ -1488,6 +1603,7 @@ tc_s390_fix_adjustable(fixP)
|| fixP->fx_r_type == BFD_RELOC_390_GOT16 || fixP->fx_r_type == BFD_RELOC_390_GOT16
|| fixP->fx_r_type == BFD_RELOC_32_GOT_PCREL || fixP->fx_r_type == BFD_RELOC_32_GOT_PCREL
|| fixP->fx_r_type == BFD_RELOC_390_GOT64 || fixP->fx_r_type == BFD_RELOC_390_GOT64
|| fixP->fx_r_type == BFD_RELOC_390_GOTENT
|| fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
return 0; return 0;
@ -1515,14 +1631,16 @@ md_apply_fix3 (fixp, valuep, seg)
value = *valuep; value = *valuep;
where = fixp->fx_frag->fr_literal + fixp->fx_where; where = fixp->fx_frag->fr_literal + fixp->fx_where;
if (fixp->fx_subsy != NULL) { if (fixp->fx_subsy != NULL)
{
if (!S_IS_DEFINED (fixp->fx_subsy)) if (!S_IS_DEFINED (fixp->fx_subsy))
as_bad_where (fixp->fx_file, fixp->fx_line, as_bad_where (fixp->fx_file, fixp->fx_line,
_("unresolved fx_subsy symbol that must be resolved")); _("unresolved fx_subsy symbol that must be resolved"));
value -= S_GET_VALUE(fixp->fx_subsy); value -= S_GET_VALUE(fixp->fx_subsy);
} }
if (fixp->fx_addsy != NULL) { if (fixp->fx_addsy != NULL)
{
/* `*valuep' may contain the value of the symbol on which the reloc /* `*valuep' may contain the value of the symbol on which the reloc
will be based; we have to remove it. */ will be based; we have to remove it. */
if (fixp->fx_addsy->sy_used_in_reloc if (fixp->fx_addsy->sy_used_in_reloc
@ -1533,21 +1651,24 @@ md_apply_fix3 (fixp, valuep, seg)
if (fixp->fx_pcrel) if (fixp->fx_pcrel)
value += fixp->fx_frag->fr_address + fixp->fx_where; value += fixp->fx_frag->fr_address + fixp->fx_where;
} else {
fixp->fx_done = 1;
} }
else
fixp->fx_done = 1;
if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED) { if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
{
const struct s390_operand *operand; const struct s390_operand *operand;
int opindex; int opindex;
opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED; opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
operand = &s390_operands[opindex]; operand = &s390_operands[opindex];
if (fixp->fx_done) { if (fixp->fx_done)
{
/* Insert the fully resolved operand value. */ /* Insert the fully resolved operand value. */
s390_insert_operand (where, operand, (offsetT) value, s390_insert_operand (where, operand, (offsetT) value,
fixp->fx_file, fixp->fx_line); fixp->fx_file, fixp->fx_line);
return 1; return 1;
} }
@ -1555,33 +1676,46 @@ md_apply_fix3 (fixp, valuep, seg)
We are only prepared to turn a few of the operands into We are only prepared to turn a few of the operands into
relocs. */ relocs. */
fixp->fx_offset = value; fixp->fx_offset = value;
if (operand->bits == 12 && operand->shift == 20) { if (operand->bits == 12 && operand->shift == 20)
{
fixp->fx_size = 2; fixp->fx_size = 2;
fixp->fx_where += 2; fixp->fx_where += 2;
fixp->fx_r_type = BFD_RELOC_390_12; fixp->fx_r_type = BFD_RELOC_390_12;
} else if (operand->bits == 12 && operand->shift == 36) { }
else if (operand->bits == 12 && operand->shift == 36)
{
fixp->fx_size = 2; fixp->fx_size = 2;
fixp->fx_where += 4; fixp->fx_where += 4;
fixp->fx_r_type = BFD_RELOC_390_12; fixp->fx_r_type = BFD_RELOC_390_12;
} else if (operand->bits == 8 && operand->shift == 8) { }
else if (operand->bits == 8 && operand->shift == 8)
{
fixp->fx_size = 1; fixp->fx_size = 1;
fixp->fx_where += 1; fixp->fx_where += 1;
fixp->fx_r_type = BFD_RELOC_8; fixp->fx_r_type = BFD_RELOC_8;
} else if (operand->bits == 16 && operand->shift == 16) { }
else if (operand->bits == 16 && operand->shift == 16)
{
fixp->fx_size = 2; fixp->fx_size = 2;
fixp->fx_where += 2; fixp->fx_where += 2;
if (operand->flags & S390_OPERAND_PCREL) { if (operand->flags & S390_OPERAND_PCREL)
{
fixp->fx_r_type = BFD_RELOC_390_PC16DBL; fixp->fx_r_type = BFD_RELOC_390_PC16DBL;
fixp->fx_offset += 2; fixp->fx_offset += 2;
} else }
else
fixp->fx_r_type = BFD_RELOC_16; fixp->fx_r_type = BFD_RELOC_16;
} else if (operand->bits == 32 && operand->shift == 16 && }
(operand->flags & S390_OPERAND_PCREL)) { else if (operand->bits == 32 && operand->shift == 16 &&
(operand->flags & S390_OPERAND_PCREL))
{
fixp->fx_size = 4; fixp->fx_size = 4;
fixp->fx_where += 2; fixp->fx_where += 2;
fixp->fx_offset += 2; fixp->fx_offset += 2;
fixp->fx_r_type = BFD_RELOC_390_PC32DBL; fixp->fx_r_type = BFD_RELOC_390_PC32DBL;
} else { }
else
{
char *sfile; char *sfile;
unsigned int sline; unsigned int sline;
@ -1596,8 +1730,11 @@ md_apply_fix3 (fixp, valuep, seg)
fixp->fx_done = 1; fixp->fx_done = 1;
return 1; return 1;
} }
} else { }
switch (fixp->fx_r_type) { else
{
switch (fixp->fx_r_type)
{
case BFD_RELOC_8: case BFD_RELOC_8:
if (fixp->fx_pcrel) if (fixp->fx_pcrel)
abort (); abort ();
@ -1606,8 +1743,10 @@ md_apply_fix3 (fixp, valuep, seg)
break; break;
case BFD_RELOC_390_12: case BFD_RELOC_390_12:
case BFD_RELOC_390_GOT12: case BFD_RELOC_390_GOT12:
if (fixp->fx_done) { if (fixp->fx_done)
{
unsigned short mop; unsigned short mop;
mop = bfd_getb16 ((unsigned char *) where); mop = bfd_getb16 ((unsigned char *) where);
mop |= (unsigned short) (value & 0xfff); mop |= (unsigned short) (value & 0xfff);
bfd_putb16 ((bfd_vma) mop, (unsigned char *) where); bfd_putb16 ((bfd_vma) mop, (unsigned char *) where);
@ -1699,13 +1838,15 @@ md_apply_fix3 (fixp, valuep, seg)
fixp->fx_done = 0; fixp->fx_done = 0;
return 1; return 1;
default: { default:
const char *reloc_name = bfd_get_reloc_code_name(fixp->fx_r_type); {
const char *reloc_name = bfd_get_reloc_code_name (fixp->fx_r_type);
if (reloc_name != NULL) if (reloc_name != NULL)
fprintf(stderr, "Gas failure, reloc type %s\n", reloc_name); fprintf (stderr, "Gas failure, reloc type %s\n", reloc_name);
else else
fprintf(stderr, "Gas failure, reloc type #%i\n", fixp->fx_r_type); fprintf (stderr, "Gas failure, reloc type #%i\n", fixp->fx_r_type);
fflush(stderr); fflush (stderr);
abort (); abort ();
} }
} }
@ -1727,7 +1868,8 @@ tc_gen_reloc (seg, fixp)
arelent *reloc; arelent *reloc;
code = fixp->fx_r_type; code = fixp->fx_r_type;
if (GOT_symbol && fixp->fx_addsy == GOT_symbol) { if (GOT_symbol && fixp->fx_addsy == GOT_symbol)
{
if ((s390_arch_size == 32 && code == BFD_RELOC_32_PCREL) || if ((s390_arch_size == 32 && code == BFD_RELOC_32_PCREL) ||
(s390_arch_size == 64 && code == BFD_RELOC_64_PCREL)) (s390_arch_size == 64 && code == BFD_RELOC_64_PCREL))
code = BFD_RELOC_390_GOTPC; code = BFD_RELOC_390_GOTPC;
@ -1754,3 +1896,14 @@ tc_gen_reloc (seg, fixp)
return reloc; return reloc;
} }
int
s390_force_relocation (fixp)
struct fix * fixp;
{
if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
return 1;
return 0;
}

View File

@ -37,11 +37,12 @@ struct fix;
pcrel, but it is easier to be safe than sorry. */ pcrel, but it is easier to be safe than sorry. */
#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \ #define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \
((FIX)->fx_addsy == NULL \ ((FIX)->fx_r_type != BFD_RELOC_390_GOTENT \
&& ((FIX)->fx_addsy == NULL \
|| (! S_IS_EXTERNAL ((FIX)->fx_addsy) \ || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \
&& ! S_IS_WEAK ((FIX)->fx_addsy) \ && ! S_IS_WEAK ((FIX)->fx_addsy) \
&& S_IS_DEFINED ((FIX)->fx_addsy) \ && S_IS_DEFINED ((FIX)->fx_addsy) \
&& ! S_IS_COMMON ((FIX)->fx_addsy))) && ! S_IS_COMMON ((FIX)->fx_addsy))))
#define tc_fix_adjustable(X) tc_s390_fix_adjustable(X) #define tc_fix_adjustable(X) tc_s390_fix_adjustable(X)
extern int tc_s390_fix_adjustable PARAMS ((struct fix *)); extern int tc_s390_fix_adjustable PARAMS ((struct fix *));
@ -52,6 +53,7 @@ extern enum bfd_architecture s390_arch PARAMS ((void));
/* The target BFD format. */ /* The target BFD format. */
#define TARGET_FORMAT s390_target_format() #define TARGET_FORMAT s390_target_format()
extern const char * s390_target_format PARAMS ((void));
/* Set the endianness we are using. */ /* Set the endianness we are using. */
#define TARGET_BYTES_BIG_ENDIAN 1 #define TARGET_BYTES_BIG_ENDIAN 1
@ -111,3 +113,6 @@ extern long md_pcrel_from_section PARAMS ((struct fix *, segT));
extern void s390_md_end PARAMS ((void)); extern void s390_md_end PARAMS ((void));
#define md_end() s390_md_end () #define md_end() s390_md_end ()
# define TC_FORCE_RELOCATION(fixp) s390_force_relocation (fixp)
extern int s390_force_relocation PARAMS ((struct fix *));