/* tc-s390.c -- Assemble for the S390
- Copyright (C) 2000-2017 Free Software Foundation, Inc.
+ Copyright (C) 2000-2020 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
This file is part of GAS, the GNU Assembler.
#include "as.h"
#include "safe-ctype.h"
#include "subsegs.h"
-#include "struc-symbol.h"
#include "dwarf2dbg.h"
#include "dw2gencfi.h"
S390_INSTR_FLAG_HTM },
{ STRING_COMMA_LEN ("z13"), STRING_COMMA_LEN ("arch11"),
S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX },
- { STRING_COMMA_LEN ("arch12"), STRING_COMMA_LEN (""),
+ { STRING_COMMA_LEN ("z14"), STRING_COMMA_LEN ("arch12"),
+ S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX },
+ { STRING_COMMA_LEN ("z15"), STRING_COMMA_LEN ("arch13"),
S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX }
};
static struct
return ptr->suffix;
}
- return BFD_RELOC_UNUSED;
+ return ELF_SUFFIX_NONE;
}
/* Structure used to hold a literal pool entry. */
{
size = bfd_get_reloc_size (reloc_howto);
if (size > nbytes)
- as_bad (_("%s relocations do not fit in %d bytes"),
+ as_bad (ngettext ("%s relocations do not fit in %d byte",
+ "%s relocations do not fit in %d bytes",
+ nbytes),
reloc_howto->name, nbytes);
where = frag_more (nbytes);
md_number_to_chars (where, 0, size);
demand_empty_rest_of_line ();
}
+/* Return true if all remaining operands in the opcode with
+ OPCODE_FLAGS can be skipped. */
+static bfd_boolean
+skip_optargs_p (unsigned int opcode_flags, const unsigned char *opindex_ptr)
+{
+ if ((opcode_flags & (S390_INSTR_FLAG_OPTPARM | S390_INSTR_FLAG_OPTPARM2))
+ && opindex_ptr[0] != '\0'
+ && opindex_ptr[1] == '\0')
+ return TRUE;
+
+ if ((opcode_flags & S390_INSTR_FLAG_OPTPARM2)
+ && opindex_ptr[0] != '\0'
+ && opindex_ptr[1] != '\0'
+ && opindex_ptr[2] == '\0')
+ return TRUE;
+ return FALSE;
+}
+
/* We need to keep a list of fixups. We can't simply generate them as
we go, because that would require us to first create the frag, and
that would screw up references to ``.''. */
operand = s390_operands + *opindex_ptr;
- if ((opcode->flags & S390_INSTR_FLAG_OPTPARM) && *str == '\0')
+ if ((opcode->flags & (S390_INSTR_FLAG_OPTPARM | S390_INSTR_FLAG_OPTPARM2))
+ && *str == '\0')
{
/* Optional parameters might need to be ORed with a
value so calling s390_insert_operand is needed. */
as_bad (_("illegal operand"));
else if (ex.X_op == O_absent)
{
- /* No operands, check if all operands can be skipped. */
- while (*opindex_ptr != 0 && operand->flags & S390_OPERAND_OPTIONAL)
- {
- if (operand->flags & S390_OPERAND_DISP)
- {
- /* An optional displacement makes the whole D(X,B)
- D(L,B) or D(B) block optional. */
- do {
- operand = s390_operands + *(++opindex_ptr);
- } while (!(operand->flags & S390_OPERAND_BASE));
- }
- operand = s390_operands + *(++opindex_ptr);
- }
if (opindex_ptr[0] == '\0')
break;
as_bad (_("missing operand"));
while (!(operand->flags & S390_OPERAND_BASE))
operand = s390_operands + *(++opindex_ptr);
+ if (*str == '\0' && skip_optargs_p (opcode->flags, &opindex_ptr[1]))
+ continue;
+
/* If there is a next operand it must be separated by a comma. */
if (opindex_ptr[1] != '\0')
{
while (opindex_ptr[1] != '\0')
{
operand = s390_operands + *(++opindex_ptr);
- if (operand->flags & S390_OPERAND_OPTIONAL)
- continue;
as_bad (_("syntax error; expected ','"));
break;
}
if (*str++ != ')')
as_bad (_("syntax error; missing ')' after base register"));
skip_optional = 0;
+
+ if (*str == '\0' && skip_optargs_p (opcode->flags, &opindex_ptr[1]))
+ continue;
+
/* If there is a next operand it must be separated by a comma. */
if (opindex_ptr[1] != '\0')
{
while (opindex_ptr[1] != '\0')
{
operand = s390_operands + *(++opindex_ptr);
- if (operand->flags & S390_OPERAND_OPTIONAL)
- continue;
as_bad (_("syntax error; expected ','"));
break;
}
str++;
}
- if ((opcode->flags & S390_INSTR_FLAG_OPTPARM) && *str == '\0')
+ if (*str == '\0' && skip_optargs_p (opcode->flags, &opindex_ptr[1]))
continue;
/* If there is a next operand it must be separated by a comma. */
while (opindex_ptr[1] != '\0')
{
operand = s390_operands + *(++opindex_ptr);
- if (operand->flags & S390_OPERAND_OPTIONAL)
- continue;
as_bad (_("syntax error; expected ','"));
break;
}
/* Emit symbol for start of literal pool. */
S_SET_SEGMENT (lp_sym, now_seg);
S_SET_VALUE (lp_sym, (valueT) frag_now_fix ());
- lp_sym->sy_frag = frag_now;
+ symbol_set_frag (lp_sym, frag_now);
while (lpe_list)
{
lpe_list = lpe_list->next;
S_SET_SEGMENT (lpe->sym, now_seg);
S_SET_VALUE (lpe->sym, (valueT) frag_now_fix ());
- lpe->sym->sy_frag = frag_now;
+ symbol_set_frag (lpe->sym, frag_now);
/* Emit literal pool entry. */
if (lpe->reloc != BFD_RELOC_UNUSED)
char *where;
if (size > lpe->nbytes)
- as_bad (_("%s relocations do not fit in %d bytes"),
+ as_bad (ngettext ("%s relocations do not fit in %d byte",
+ "%s relocations do not fit in %d bytes",
+ lpe->nbytes),
reloc_howto->name, lpe->nbytes);
where = frag_more (lpe->nbytes);
md_number_to_chars (where, 0, size);
valueT
md_section_align (asection *seg, valueT addr)
{
- int align = bfd_get_section_alignment (stdoutput, seg);
+ int align = bfd_section_alignment (seg);
return ((addr + (1 << align) - 1) & -(1 << align));
}
}
else if (operand->bits == 20 && operand->shift == 20)
{
- fixP->fx_size = 2;
+ fixP->fx_size = 4;
fixP->fx_where += 2;
fixP->fx_r_type = BFD_RELOC_390_20;
}