mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-20 01:50:24 +08:00
Do not optimize BFD_RELOC_390_GOTENT relocs.
Always generate relocs for VT_ relocs.
This commit is contained in:
@ -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>
|
||||
|
||||
* doc/as.texinfo: Put @c man begin to generate the as man page.
|
||||
|
@ -313,13 +313,18 @@ init_default_arch ()
|
||||
{
|
||||
if (current_arch_requested)
|
||||
return;
|
||||
if (strcmp(default_arch, "s390") == 0) {
|
||||
|
||||
if (strcmp(default_arch, "s390") == 0)
|
||||
{
|
||||
s390_arch_size = 32;
|
||||
current_architecture = S390_OPCODE_ESA;
|
||||
} else if (strcmp(default_arch, "s390x") == 0) {
|
||||
}
|
||||
else if (strcmp(default_arch, "s390x") == 0)
|
||||
{
|
||||
s390_arch_size = 64;
|
||||
current_architecture = S390_OPCODE_ESAME;
|
||||
} else
|
||||
}
|
||||
else
|
||||
as_fatal ("Invalid default architecture, broken assembler.");
|
||||
current_arch_mask = 1 << current_architecture;
|
||||
}
|
||||
@ -341,7 +346,8 @@ md_parse_option (c, arg)
|
||||
int c;
|
||||
char *arg;
|
||||
{
|
||||
switch (c) {
|
||||
switch (c)
|
||||
{
|
||||
/* -k: Ignore for FreeBSD compatibility. */
|
||||
case 'k':
|
||||
break;
|
||||
@ -352,20 +358,25 @@ md_parse_option (c, arg)
|
||||
else if (arg != NULL && strcmp (arg, "no-regnames") == 0)
|
||||
reg_names_p = false;
|
||||
|
||||
else {
|
||||
else
|
||||
{
|
||||
as_bad (_("invalid switch -m%s"), arg);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
if (arg != NULL && strcmp (arg, "esa") == 0) {
|
||||
if (arg != NULL && strcmp (arg, "esa") == 0)
|
||||
{
|
||||
current_architecture = S390_OPCODE_ESA;
|
||||
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;
|
||||
s390_arch_size = 64;
|
||||
} else
|
||||
}
|
||||
else
|
||||
as_bad ("invalid architecture -A%s", arg);
|
||||
current_arch_mask = 1 << current_architecture;
|
||||
current_arch_requested = 1;
|
||||
@ -392,11 +403,11 @@ void
|
||||
md_show_usage (stream)
|
||||
FILE *stream;
|
||||
{
|
||||
fprintf(stream, _("\
|
||||
fprintf (stream, _("\
|
||||
S390 options:\n\
|
||||
-mregnames \tAllow 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\
|
||||
-Qy, -Qn \tignored\n"));
|
||||
}
|
||||
@ -421,7 +432,8 @@ md_begin ()
|
||||
s390_opformat_hash = hash_new ();
|
||||
|
||||
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);
|
||||
if (retval != (const char *) NULL)
|
||||
{
|
||||
@ -435,7 +447,8 @@ md_begin ()
|
||||
s390_opcode_hash = hash_new ();
|
||||
|
||||
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);
|
||||
if (retval != (const char *) NULL)
|
||||
{
|
||||
@ -457,11 +470,10 @@ md_begin ()
|
||||
void
|
||||
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);
|
||||
} else {
|
||||
else
|
||||
bfd_set_arch_mach (stdoutput, bfd_arch_s390, bfd_mach_s390_esa);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -470,7 +482,8 @@ s390_align_code (fragP, count)
|
||||
int count;
|
||||
{
|
||||
/* We use nop pattern 0x0707. */
|
||||
if (count > 0) {
|
||||
if (count > 0)
|
||||
{
|
||||
memset(fragP->fr_literal + fragP->fr_fix, 0x07, count);
|
||||
fragP->fr_var = count;
|
||||
}
|
||||
@ -489,7 +502,8 @@ s390_insert_operand (insn, operand, val, file, line)
|
||||
addressT uval;
|
||||
int offset;
|
||||
|
||||
if (operand->flags & (S390_OPERAND_SIGNED|S390_OPERAND_PCREL)) {
|
||||
if (operand->flags & (S390_OPERAND_SIGNED|S390_OPERAND_PCREL))
|
||||
{
|
||||
offsetT min, max;
|
||||
|
||||
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)
|
||||
val >>= 1;
|
||||
/* Check for underflow / overflow. */
|
||||
if (val < min || val > max) {
|
||||
if (val < min || val > max)
|
||||
{
|
||||
const char *err =
|
||||
"operand out of range (%s not between %ld and %ld)";
|
||||
char buf[100];
|
||||
|
||||
if (operand->flags & S390_OPERAND_PCREL) {
|
||||
if (operand->flags & S390_OPERAND_PCREL)
|
||||
{
|
||||
val <<= 1;
|
||||
min <<= 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. */
|
||||
uval = (addressT) val & ((((addressT) 1 << (operand->bits-1)) << 1) - 1);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
addressT min, max;
|
||||
|
||||
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)
|
||||
uval--;
|
||||
/* Check for underflow / overflow. */
|
||||
if (uval < min || uval > max) {
|
||||
if (uval < min || uval > max)
|
||||
{
|
||||
const char *err =
|
||||
"operand out of range (%s not between %ld and %ld)";
|
||||
char buf[100];
|
||||
|
||||
if (operand->flags & S390_OPERAND_LENGTH) {
|
||||
if (operand->flags & S390_OPERAND_LENGTH)
|
||||
{
|
||||
uval++;
|
||||
min++;
|
||||
max++;
|
||||
@ -550,25 +570,29 @@ s390_insert_operand (insn, operand, val, file, line)
|
||||
offset = operand->shift + operand->bits;
|
||||
uval <<= (-offset) & 7;
|
||||
insn += (offset - 1)/8;
|
||||
while (uval != 0) {
|
||||
while (uval != 0)
|
||||
{
|
||||
*insn-- |= uval;
|
||||
uval >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* Structure used to hold suffixes. */
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
ELF_SUFFIX_NONE = 0,
|
||||
ELF_SUFFIX_GOT,
|
||||
ELF_SUFFIX_PLT,
|
||||
ELF_SUFFIX_GOTENT
|
||||
} elf_suffix_type;
|
||||
}
|
||||
elf_suffix_type;
|
||||
|
||||
struct map_bfd {
|
||||
struct map_bfd
|
||||
{
|
||||
char *string;
|
||||
int length;
|
||||
elf_suffix_type suffix;
|
||||
};
|
||||
};
|
||||
|
||||
/* Parse @got/@plt/@gotoff. and return the desired relocation. */
|
||||
static elf_suffix_type
|
||||
@ -576,7 +600,8 @@ s390_elf_suffix (str_p, exp_p)
|
||||
char **str_p;
|
||||
expressionS *exp_p;
|
||||
{
|
||||
static struct map_bfd mapping[] = {
|
||||
static struct map_bfd mapping[] =
|
||||
{
|
||||
{ "got", 3, ELF_SUFFIX_GOT },
|
||||
{ "got12", 5, ELF_SUFFIX_GOT },
|
||||
{ "plt", 3, ELF_SUFFIX_PLT },
|
||||
@ -599,19 +624,22 @@ s390_elf_suffix (str_p, exp_p)
|
||||
|
||||
for (ptr = &mapping[0]; ptr->length > 0; ptr++)
|
||||
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)
|
||||
as_warn (_("identifier+constant@%s means identifier@%s+constant"),
|
||||
ptr->string, ptr->string);
|
||||
/* Now check for identifier@suffix+constant. */
|
||||
if (*str == '-' || *str == '+') {
|
||||
if (*str == '-' || *str == '+')
|
||||
{
|
||||
char *orig_line = input_line_pointer;
|
||||
expressionS new_exp;
|
||||
|
||||
input_line_pointer = str;
|
||||
expression (&new_exp);
|
||||
|
||||
switch (new_exp.X_op) {
|
||||
switch (new_exp.X_op)
|
||||
{
|
||||
case O_constant: /* X_add_number (a constant expression). */
|
||||
exp_p->X_add_number += new_exp.X_add_number;
|
||||
str = input_line_pointer;
|
||||
@ -649,7 +677,8 @@ s390_elf_suffix (str_p, exp_p)
|
||||
}
|
||||
|
||||
/* Structure used to hold a literal pool entry. */
|
||||
struct s390_lpe {
|
||||
struct s390_lpe
|
||||
{
|
||||
struct s390_lpe *next;
|
||||
expressionS ex;
|
||||
FLONUM_TYPE floatnum; /* used if X_op == O_big && X_add_number <= 0 */
|
||||
@ -657,7 +686,7 @@ struct s390_lpe {
|
||||
int nbytes;
|
||||
bfd_reloc_code_real_type reloc;
|
||||
symbolS *sym;
|
||||
};
|
||||
};
|
||||
|
||||
static struct s390_lpe *lpe_free_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)
|
||||
return 0;
|
||||
|
||||
switch (exp1->X_op) {
|
||||
switch (exp1->X_op)
|
||||
{
|
||||
case O_constant: /* X_add_number must be equal. */
|
||||
case O_register:
|
||||
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';
|
||||
|
||||
reloc = BFD_RELOC_UNUSED;
|
||||
if (suffix == ELF_SUFFIX_GOT) {
|
||||
if (suffix == ELF_SUFFIX_GOT)
|
||||
{
|
||||
if (nbytes == 2)
|
||||
reloc = BFD_RELOC_390_GOT16;
|
||||
else if (nbytes == 4)
|
||||
reloc = BFD_RELOC_32_GOT_PCREL;
|
||||
else if (nbytes == 8)
|
||||
reloc = BFD_RELOC_390_GOT64;
|
||||
} else if (suffix == ELF_SUFFIX_PLT) {
|
||||
}
|
||||
else if (suffix == ELF_SUFFIX_PLT)
|
||||
{
|
||||
if (nbytes == 4)
|
||||
reloc = BFD_RELOC_390_PLT32;
|
||||
else if (nbytes == 8)
|
||||
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"));
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
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 (memcmp(&generic_floating_point_number, &lpe->floatnum,
|
||||
sizeof(FLONUM_TYPE)) == 0)
|
||||
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 (memcmp (&generic_floating_point_number, &lpe->floatnum,
|
||||
sizeof (FLONUM_TYPE)) == 0)
|
||||
break;
|
||||
} else if (exp_p->X_add_number == lpe->ex.X_add_number) {
|
||||
if (memcmp(generic_bignum, lpe->bignum,
|
||||
sizeof(LITTLENUM_TYPE)*exp_p->X_add_number) == 0)
|
||||
}
|
||||
else if (exp_p->X_add_number == lpe->ex.X_add_number)
|
||||
{
|
||||
if (memcmp (generic_bignum, lpe->bignum,
|
||||
sizeof (LITTLENUM_TYPE)*exp_p->X_add_number) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Processing for 'normal' data types. */
|
||||
for (lpe = lpe_list; lpe != NULL; lpe = lpe->next)
|
||||
if (lpe->nbytes == nbytes && lpe->reloc == reloc &&
|
||||
s390_exp_compare(exp_p, &lpe->ex) != 0)
|
||||
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_free_list = lpe_free_list->next;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
lpe = (struct s390_lpe *) xmalloc(sizeof(struct s390_lpe));
|
||||
}
|
||||
|
||||
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)
|
||||
lpe->floatnum = generic_floating_point_number;
|
||||
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));
|
||||
else
|
||||
as_bad(_("Big number is too big"));
|
||||
as_bad (_("Big number is too big"));
|
||||
}
|
||||
|
||||
lpe->nbytes = nbytes;
|
||||
lpe->reloc = reloc;
|
||||
/* Literal pool name defined ? */
|
||||
if (lp_sym == NULL) {
|
||||
if (lp_sym == NULL)
|
||||
{
|
||||
sprintf(tmp_name, ".L\001%i", lp_count);
|
||||
lp_sym = symbol_make(tmp_name);
|
||||
}
|
||||
|
||||
/* Make name for literal pool entry. */
|
||||
sprintf(tmp_name, ".L\001%i\002%i", lp_count, lpe_count);
|
||||
lpe_count++;
|
||||
lpe->sym = symbol_make(tmp_name);
|
||||
|
||||
/* Add to literal pool list. */
|
||||
lpe->next = NULL;
|
||||
if (lpe_list_tail != NULL) {
|
||||
if (lpe_list_tail != NULL)
|
||||
{
|
||||
lpe_list_tail->next = lpe;
|
||||
lpe_list_tail = lpe;
|
||||
} else
|
||||
}
|
||||
else
|
||||
lpe_list = lpe_list_tail = lpe;
|
||||
}
|
||||
|
||||
@ -847,15 +902,20 @@ s390_elf_cons (nbytes)
|
||||
expressionS exp;
|
||||
elf_suffix_type suffix;
|
||||
|
||||
if (is_it_end_of_statement ()) {
|
||||
if (is_it_end_of_statement ())
|
||||
{
|
||||
demand_empty_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
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;
|
||||
reloc_howto_type *reloc_howto;
|
||||
int size;
|
||||
@ -874,7 +934,8 @@ s390_elf_cons (nbytes)
|
||||
else
|
||||
reloc = BFD_RELOC_UNUSED;
|
||||
|
||||
if (reloc != BFD_RELOC_UNUSED) {
|
||||
if (reloc != BFD_RELOC_UNUSED)
|
||||
{
|
||||
reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc);
|
||||
size = bfd_get_reloc_size (reloc_howto);
|
||||
if (size > nbytes)
|
||||
@ -884,11 +945,14 @@ s390_elf_cons (nbytes)
|
||||
md_number_to_chars (where, 0, size);
|
||||
fix_new_exp (frag_now, where - frag_now->fr_literal,
|
||||
size, &exp, reloc_howto->pc_relative, reloc);
|
||||
} else
|
||||
}
|
||||
else
|
||||
as_bad (_("relocation not applicable"));
|
||||
} else
|
||||
}
|
||||
else
|
||||
emit_expr (&exp, (unsigned int) nbytes);
|
||||
} while (*input_line_pointer++ == ',');
|
||||
}
|
||||
while (*input_line_pointer++ == ',');
|
||||
|
||||
input_line_pointer--; /* Put terminator back into stream. */
|
||||
demand_empty_rest_of_line ();
|
||||
@ -899,11 +963,11 @@ s390_elf_cons (nbytes)
|
||||
that would screw up references to ``.''. */
|
||||
|
||||
struct s390_fixup
|
||||
{
|
||||
{
|
||||
expressionS exp;
|
||||
int opindex;
|
||||
bfd_reloc_code_real_type reloc;
|
||||
};
|
||||
};
|
||||
|
||||
#define MAX_INSN_FIXUPS (4)
|
||||
|
||||
@ -932,13 +996,15 @@ md_gather_operands (str, insn, opcode)
|
||||
|
||||
/* Gather the operands. */
|
||||
fc = 0;
|
||||
for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++) {
|
||||
for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
|
||||
{
|
||||
expressionS ex;
|
||||
char *hold;
|
||||
|
||||
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
|
||||
register is skipped (X is optional). For D(L,B) the base
|
||||
register will be the skipped operand, because L is NOT
|
||||
@ -962,9 +1028,12 @@ md_gather_operands (str, insn, opcode)
|
||||
as_bad (_("illegal operand"));
|
||||
else if (ex.X_op == O_absent)
|
||||
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);
|
||||
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
|
||||
expression returned by s390_lit_suffix. */
|
||||
if (fc >= MAX_INSN_FIXUPS)
|
||||
@ -973,18 +1042,24 @@ md_gather_operands (str, insn, opcode)
|
||||
fixups[fc].opindex = *opindex_ptr;
|
||||
fixups[fc].reloc = BFD_RELOC_UNUSED;
|
||||
++fc;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((operand->flags & S390_OPERAND_INDEX) && ex.X_add_number == 0)
|
||||
as_warn("index register specified but zero");
|
||||
if ((operand->flags & S390_OPERAND_BASE) && ex.X_add_number == 0)
|
||||
as_warn("base register specified but zero");
|
||||
s390_insert_operand (insn, operand, ex.X_add_number, NULL, 0);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
suffix = s390_elf_suffix (&str, &ex);
|
||||
suffix = s390_lit_suffix (&str, &ex, suffix);
|
||||
reloc = BFD_RELOC_UNUSED;
|
||||
if (suffix == ELF_SUFFIX_GOT) {
|
||||
|
||||
if (suffix == ELF_SUFFIX_GOT)
|
||||
{
|
||||
if (operand->flags & S390_OPERAND_DISP)
|
||||
reloc = BFD_RELOC_390_GOT12;
|
||||
else if ((operand->flags & S390_OPERAND_SIGNED) &&
|
||||
@ -993,14 +1068,18 @@ md_gather_operands (str, insn, opcode)
|
||||
else if ((operand->flags & S390_OPERAND_PCREL) &&
|
||||
(operand->bits == 32))
|
||||
reloc = BFD_RELOC_390_GOTENT;
|
||||
} else if (suffix == ELF_SUFFIX_PLT) {
|
||||
}
|
||||
else if (suffix == ELF_SUFFIX_PLT)
|
||||
{
|
||||
if ((operand->flags & S390_OPERAND_PCREL) &&
|
||||
(operand->bits == 16))
|
||||
reloc = BFD_RELOC_390_PLT16DBL;
|
||||
else if ((operand->flags & S390_OPERAND_PCREL) &&
|
||||
(operand->bits == 32))
|
||||
reloc = BFD_RELOC_390_PLT32DBL;
|
||||
} else if (suffix == ELF_SUFFIX_GOTENT) {
|
||||
}
|
||||
else if (suffix == ELF_SUFFIX_GOTENT)
|
||||
{
|
||||
if ((operand->flags & S390_OPERAND_PCREL) &&
|
||||
(operand->bits == 32))
|
||||
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
|
||||
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. */
|
||||
if (*str != '(') {
|
||||
if (*str != '(')
|
||||
{
|
||||
/* Check if parethesed block can be skipped. If the next
|
||||
operand is neiter an optional operand nor a base register
|
||||
then we have a syntax error. */
|
||||
@ -1035,11 +1116,15 @@ md_gather_operands (str, insn, opcode)
|
||||
operand = s390_operands + *(++opindex_ptr);
|
||||
|
||||
/* 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++ != ',')
|
||||
as_bad(_("syntax error; expected ,"));
|
||||
}
|
||||
} else { /* We found an opening parentheses. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We found an opening parentheses. */
|
||||
str++;
|
||||
for (f = str; *f != '\0'; f++)
|
||||
if (*f == ',' || *f == ')')
|
||||
@ -1047,33 +1132,44 @@ md_gather_operands (str, insn, opcode)
|
||||
/* If there is no comma until the closing parentheses OR
|
||||
there is a comma right after the opening parentheses,
|
||||
we have to skip optional operands. */
|
||||
if (*f == ',' && f == str) { /* comma directly after '(' ? */
|
||||
if (*f == ',' && f == str)
|
||||
{
|
||||
/* comma directly after '(' ? */
|
||||
skip_optional = 1;
|
||||
str++;
|
||||
} else
|
||||
}
|
||||
else
|
||||
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. */
|
||||
if (*str++ != ')')
|
||||
as_bad(_("syntax error; missing ')' after base register"));
|
||||
as_bad (_("syntax error; missing ')' after base register"));
|
||||
skip_optional = 0;
|
||||
/* 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++ != ',')
|
||||
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
|
||||
of D(L,B). In this case the base register has to be skipped. */
|
||||
if (*str == ')') {
|
||||
if (*str == ')')
|
||||
{
|
||||
operand = s390_operands + *(++opindex_ptr);
|
||||
|
||||
if (!(operand->flags & S390_OPERAND_BASE))
|
||||
as_bad (_("syntax error; ')' not allowed here"));
|
||||
str++;
|
||||
}
|
||||
/* 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++ != ',')
|
||||
as_bad(_("syntax error; expected ,"));
|
||||
}
|
||||
@ -1083,7 +1179,8 @@ md_gather_operands (str, insn, opcode)
|
||||
while (isspace (*str))
|
||||
++str;
|
||||
|
||||
if (*str != '\0') {
|
||||
if (*str != '\0')
|
||||
{
|
||||
char *linefeed;
|
||||
|
||||
if ((linefeed = strchr(str, '\n')) != NULL)
|
||||
@ -1095,7 +1192,7 @@ md_gather_operands (str, insn, opcode)
|
||||
|
||||
/* Write out the instruction. */
|
||||
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
|
||||
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
|
||||
not a very exciting feature. We pick a BFD reloc type in
|
||||
md_apply_fix3. */
|
||||
for (i = 0; i < fc; i++) {
|
||||
for (i = 0; i < fc; i++)
|
||||
{
|
||||
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;
|
||||
fixS *fixP;
|
||||
int size;
|
||||
@ -1118,7 +1217,7 @@ md_gather_operands (str, insn, opcode)
|
||||
size = bfd_get_reloc_size (reloc_howto);
|
||||
|
||||
if (size < 1 || size > 4)
|
||||
abort();
|
||||
abort ();
|
||||
|
||||
fixP = fix_new_exp (frag_now,
|
||||
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 ||
|
||||
fixups[i].reloc == BFD_RELOC_390_GOT16)
|
||||
fixP->fx_no_overflow = 1;
|
||||
} else
|
||||
}
|
||||
else
|
||||
fix_new_exp (frag_now, f - frag_now->fr_literal, 4, &fixups[i].exp,
|
||||
(operand->flags & S390_OPERAND_PCREL) != 0,
|
||||
((bfd_reloc_code_real_type)
|
||||
@ -1157,16 +1257,19 @@ md_assemble (str)
|
||||
|
||||
/* Look up the opcode in the hash table. */
|
||||
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);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(insn, opcode->opcode, sizeof(insn));
|
||||
md_gather_operands(s, insn, opcode);
|
||||
memcpy (insn, opcode->opcode, sizeof(insn));
|
||||
md_gather_operands (s, insn, opcode);
|
||||
}
|
||||
|
||||
#ifndef WORKING_DOT_WORD
|
||||
@ -1225,28 +1328,35 @@ s390_insn(ignore)
|
||||
/* Look up the opcode in the hash table. */
|
||||
opformat = (struct s390_opcode *)
|
||||
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);
|
||||
return;
|
||||
}
|
||||
input_line_pointer = s;
|
||||
expression (&exp);
|
||||
if (exp.X_op == O_constant) {
|
||||
if (exp.X_op == O_constant)
|
||||
{
|
||||
if (opformat->oplen == 4 ||
|
||||
(opformat->oplen == 2 && exp.X_op < 0x10000))
|
||||
md_number_to_chars (insn, exp.X_add_number, opformat->oplen);
|
||||
else
|
||||
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 &&
|
||||
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[2], generic_bignum[1], 2);
|
||||
md_number_to_chars (&insn[4], generic_bignum[0], 2);
|
||||
} else
|
||||
}
|
||||
else
|
||||
as_bad(_("Invalid .insn format\n"));
|
||||
} else
|
||||
}
|
||||
else
|
||||
as_bad (_("second operand of .insn not a constant\n"));
|
||||
if (*input_line_pointer++ != ',')
|
||||
as_bad (_("missing comma after insn constant\n"));
|
||||
@ -1312,7 +1422,8 @@ s390_literals (ignore)
|
||||
S_SET_VALUE (lp_sym, (valueT) frag_now_fix ());
|
||||
lp_sym->sy_frag = frag_now;
|
||||
|
||||
while (lpe_list) {
|
||||
while (lpe_list)
|
||||
{
|
||||
lpe = lpe_list;
|
||||
lpe_list = lpe_list->next;
|
||||
S_SET_SEGMENT (lpe->sym, now_seg);
|
||||
@ -1320,7 +1431,8 @@ s390_literals (ignore)
|
||||
lpe->sym->sy_frag = frag_now;
|
||||
|
||||
/* Emit literal pool entry. */
|
||||
if (lpe->reloc != BFD_RELOC_UNUSED) {
|
||||
if (lpe->reloc != BFD_RELOC_UNUSED)
|
||||
{
|
||||
reloc_howto_type *reloc_howto =
|
||||
bfd_reloc_type_lookup (stdoutput, lpe->reloc);
|
||||
int size = bfd_get_reloc_size (reloc_howto);
|
||||
@ -1333,12 +1445,15 @@ s390_literals (ignore)
|
||||
md_number_to_chars (where, 0, size);
|
||||
fix_new_exp (frag_now, where - frag_now->fr_literal,
|
||||
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)
|
||||
generic_floating_point_number = lpe->floatnum;
|
||||
else
|
||||
memcpy(generic_bignum, lpe->bignum,
|
||||
memcpy (generic_bignum, lpe->bignum,
|
||||
lpe->ex.X_add_number*sizeof(LITTLENUM_TYPE));
|
||||
}
|
||||
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_32_GOT_PCREL
|
||||
|| 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_ENTRY)
|
||||
return 0;
|
||||
@ -1515,14 +1631,16 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||
value = *valuep;
|
||||
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))
|
||||
as_bad_where (fixp->fx_file, fixp->fx_line,
|
||||
_("unresolved fx_subsy symbol that must be resolved"));
|
||||
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
|
||||
will be based; we have to remove it. */
|
||||
if (fixp->fx_addsy->sy_used_in_reloc
|
||||
@ -1533,21 +1651,24 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||
|
||||
if (fixp->fx_pcrel)
|
||||
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;
|
||||
int opindex;
|
||||
|
||||
opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
|
||||
operand = &s390_operands[opindex];
|
||||
|
||||
if (fixp->fx_done) {
|
||||
if (fixp->fx_done)
|
||||
{
|
||||
/* Insert the fully resolved operand value. */
|
||||
s390_insert_operand (where, operand, (offsetT) value,
|
||||
fixp->fx_file, fixp->fx_line);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1555,33 +1676,46 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||
We are only prepared to turn a few of the operands into
|
||||
relocs. */
|
||||
fixp->fx_offset = value;
|
||||
if (operand->bits == 12 && operand->shift == 20) {
|
||||
if (operand->bits == 12 && operand->shift == 20)
|
||||
{
|
||||
fixp->fx_size = 2;
|
||||
fixp->fx_where += 2;
|
||||
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_where += 4;
|
||||
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_where += 1;
|
||||
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_where += 2;
|
||||
if (operand->flags & S390_OPERAND_PCREL) {
|
||||
if (operand->flags & S390_OPERAND_PCREL)
|
||||
{
|
||||
fixp->fx_r_type = BFD_RELOC_390_PC16DBL;
|
||||
fixp->fx_offset += 2;
|
||||
} else
|
||||
}
|
||||
else
|
||||
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_where += 2;
|
||||
fixp->fx_offset += 2;
|
||||
fixp->fx_r_type = BFD_RELOC_390_PC32DBL;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
char *sfile;
|
||||
unsigned int sline;
|
||||
|
||||
@ -1596,8 +1730,11 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||
fixp->fx_done = 1;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
switch (fixp->fx_r_type) {
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (fixp->fx_r_type)
|
||||
{
|
||||
case BFD_RELOC_8:
|
||||
if (fixp->fx_pcrel)
|
||||
abort ();
|
||||
@ -1606,8 +1743,10 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||
break;
|
||||
case BFD_RELOC_390_12:
|
||||
case BFD_RELOC_390_GOT12:
|
||||
if (fixp->fx_done) {
|
||||
if (fixp->fx_done)
|
||||
{
|
||||
unsigned short mop;
|
||||
|
||||
mop = bfd_getb16 ((unsigned char *) where);
|
||||
mop |= (unsigned short) (value & 0xfff);
|
||||
bfd_putb16 ((bfd_vma) mop, (unsigned char *) where);
|
||||
@ -1699,13 +1838,15 @@ md_apply_fix3 (fixp, valuep, seg)
|
||||
fixp->fx_done = 0;
|
||||
return 1;
|
||||
|
||||
default: {
|
||||
const char *reloc_name = bfd_get_reloc_code_name(fixp->fx_r_type);
|
||||
default:
|
||||
{
|
||||
const char *reloc_name = bfd_get_reloc_code_name (fixp->fx_r_type);
|
||||
|
||||
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
|
||||
fprintf(stderr, "Gas failure, reloc type #%i\n", fixp->fx_r_type);
|
||||
fflush(stderr);
|
||||
fprintf (stderr, "Gas failure, reloc type #%i\n", fixp->fx_r_type);
|
||||
fflush (stderr);
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
@ -1727,7 +1868,8 @@ tc_gen_reloc (seg, fixp)
|
||||
arelent *reloc;
|
||||
|
||||
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) ||
|
||||
(s390_arch_size == 64 && code == BFD_RELOC_64_PCREL))
|
||||
code = BFD_RELOC_390_GOTPC;
|
||||
@ -1754,3 +1896,14 @@ tc_gen_reloc (seg, fixp)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -37,11 +37,12 @@ struct fix;
|
||||
pcrel, but it is easier to be safe than sorry. */
|
||||
|
||||
#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_WEAK ((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)
|
||||
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. */
|
||||
#define TARGET_FORMAT s390_target_format()
|
||||
extern const char * s390_target_format PARAMS ((void));
|
||||
|
||||
/* Set the endianness we are using. */
|
||||
#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));
|
||||
#define md_end() s390_md_end ()
|
||||
|
||||
# define TC_FORCE_RELOCATION(fixp) s390_force_relocation (fixp)
|
||||
extern int s390_force_relocation PARAMS ((struct fix *));
|
||||
|
Reference in New Issue
Block a user