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>
* 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)
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;
}

View File

@ -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 *));