mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-20 09:58:19 +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>
|
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.
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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 *));
|
||||||
|
Reference in New Issue
Block a user