/* tc-s390.c -- Assemble for the S390
- Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
- Free Software Foundation, Inc.
+ Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+ 2009 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
This file is part of GAS, the GNU Assembler.
/* The target specific pseudo-ops which we support. */
/* Define the prototypes for the pseudo-ops */
-static void s390_byte PARAMS ((int));
-static void s390_elf_cons PARAMS ((int));
-static void s390_bss PARAMS ((int));
-static void s390_insn PARAMS ((int));
-static void s390_literals PARAMS ((int));
+static void s390_byte (int);
+static void s390_elf_cons (int);
+static void s390_bss (int);
+static void s390_insn (int);
+static void s390_literals (int);
const pseudo_typeS md_pseudo_table[] =
{
{ "long", s390_elf_cons, 4 },
{ "quad", s390_elf_cons, 8 },
{ "ltorg", s390_literals, 0 },
- { "string", stringer, 2 },
+ { "string", stringer, 8 + 1 },
{ NULL, NULL, 0 }
};
#define REG_NAME_CNT (sizeof (pre_defined_registers) / sizeof (struct pd_reg))
-static int reg_name_search
- PARAMS ((const struct pd_reg *, int, const char *));
-static bfd_boolean register_name PARAMS ((expressionS *));
-static void init_default_arch PARAMS ((void));
-static void s390_insert_operand
- PARAMS ((unsigned char *, const struct s390_operand *, offsetT, char *,
- unsigned int));
-static char *md_gather_operands
- PARAMS ((char *, unsigned char *, const struct s390_opcode *));
-
/* Given NAME, find the register number associated with that name, return
the integer value associated with the given name or -1 on failure. */
static int
-reg_name_search (regs, regcount, name)
- const struct pd_reg *regs;
- int regcount;
- const char *name;
+reg_name_search (const struct pd_reg *regs, int regcount, const char *name)
{
int middle, low, high;
int cmp;
*/
static bfd_boolean
-register_name (expressionP)
- expressionS *expressionP;
+register_name (expressionS *expressionP)
{
int reg_number;
char *name;
/* Initialize the default opcode arch and word size from the default
architecture name if not specified by an option. */
static void
-init_default_arch ()
+init_default_arch (void)
{
if (strcmp (default_arch, "s390") == 0)
{
s390_arch_size = 64;
}
else
- as_fatal ("Invalid default architecture, broken assembler.");
+ as_fatal (_("Invalid default architecture, broken assembler."));
if (current_mode_mask == 0)
{
/* Called by TARGET_FORMAT. */
const char *
-s390_target_format ()
+s390_target_format (void)
{
/* We don't get a chance to initialize anything before we're called,
so handle that now. */
}
int
-md_parse_option (c, arg)
- int c;
- char *arg;
+md_parse_option (int c, char *arg)
{
switch (c)
{
current_cpu = S390_OPCODE_Z9_109;
else if (strcmp (arg + 5, "z9-ec") == 0)
current_cpu = S390_OPCODE_Z9_EC;
+ else if (strcmp (arg + 5, "z10") == 0)
+ current_cpu = S390_OPCODE_Z10;
else
{
as_bad (_("invalid switch -m%s"), arg);
else if (arg != NULL && strcmp (arg, "esame") == 0)
current_cpu = S390_OPCODE_Z900;
else
- as_bad ("invalid architecture -A%s", arg);
+ as_bad (_("invalid architecture -A%s"), arg);
break;
/* -V: SVR4 argument to print version ID. */
}
void
-md_show_usage (stream)
- FILE *stream;
+md_show_usage (FILE *stream)
{
fprintf (stream, _("\
S390 options:\n\
opened. */
void
-md_begin ()
+md_begin (void)
{
register const struct s390_opcode *op;
const struct s390_opcode *op_end;
/* Give a warning if the combination -m64-bit and -Aesa is used. */
if (s390_arch_size == 64 && current_cpu < S390_OPCODE_Z900)
- as_warn ("The 64 bit file format is used without esame instructions.");
+ as_warn (_("The 64 bit file format is used without esame instructions."));
s390_cie_data_alignment = -s390_arch_size / 8;
op_end = s390_opformats + s390_num_opformats;
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, (void *) op);
if (retval != (const char *) NULL)
{
as_bad (_("Internal assembler error for instruction format %s"),
op_end = s390_opcodes + s390_num_opcodes;
for (op = s390_opcodes; op < op_end; op++)
- if (op->min_cpu <= current_cpu)
- {
- retval = hash_insert (s390_opcode_hash, op->name, (PTR) op);
- if (retval != (const char *) NULL)
- {
- as_bad (_("Internal assembler error for instruction %s"),
- op->name);
- dup_insn = TRUE;
- }
- while (op < op_end - 1 && strcmp (op->name, op[1].name) == 0)
+ {
+ while (op < op_end - 1 && strcmp(op->name, op[1].name) == 0)
+ {
+ if (op->min_cpu <= current_cpu && (op->modes & current_mode_mask))
+ break;
op++;
+ }
+ retval = hash_insert (s390_opcode_hash, op->name, (void *) op);
+ if (retval != (const char *) NULL)
+ {
+ as_bad (_("Internal assembler error for instruction %s"),
+ op->name);
+ dup_insn = TRUE;
+ }
+ while (op < op_end - 1 && strcmp (op->name, op[1].name) == 0)
+ op++;
}
if (dup_insn)
/* Called after all assembly has been done. */
void
-s390_md_end ()
+s390_md_end (void)
{
if (s390_arch_size == 64)
bfd_set_arch_mach (stdoutput, bfd_arch_s390, bfd_mach_s390_64);
/* Insert an operand value into an instruction. */
static void
-s390_insert_operand (insn, operand, val, file, line)
- unsigned char *insn;
- const struct s390_operand *operand;
- offsetT val;
- char *file;
- unsigned int line;
+s390_insert_operand (unsigned char *insn,
+ const struct s390_operand *operand,
+ offsetT val,
+ char *file,
+ unsigned int line)
{
addressT uval;
int offset;
if (val < min || val > max)
{
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];
if (operand->flags & S390_OPERAND_PCREL)
bfd_reloc_code_real_type reloc;
};
-static bfd_reloc_code_real_type s390_tls_suffix
- PARAMS ((char **, expressionS *));
-
/* Parse tls marker and return the desired relocation. */
static bfd_reloc_code_real_type
-s390_tls_suffix (str_p, exp_p)
- char **str_p;
- expressionS *exp_p;
+s390_tls_suffix (char **str_p, expressionS *exp_p)
{
static struct map_tls mapping[] =
{
elf_suffix_type suffix;
};
-static elf_suffix_type s390_elf_suffix PARAMS ((char **, expressionS *));
-static int s390_exp_compare PARAMS ((expressionS *exp1, expressionS *exp2));
-static elf_suffix_type s390_lit_suffix
- PARAMS ((char **, expressionS *, elf_suffix_type));
-
/* Parse @got/@plt/@gotoff. and return the desired relocation. */
static elf_suffix_type
-s390_elf_suffix (str_p, exp_p)
- char **str_p;
- expressionS *exp_p;
+s390_elf_suffix (char **str_p, expressionS *exp_p)
{
static struct map_bfd mapping[] =
{
static int lpe_count = 0;
static int
-s390_exp_compare (exp1, exp2)
- expressionS *exp1;
- expressionS *exp2;
+s390_exp_compare (expressionS *exp1, expressionS *exp2)
{
if (exp1->X_op != exp2->X_op)
return 0;
/* Test for @lit and if its present make an entry in the literal pool and
modify the current expression to be an offset into the literal pool. */
static elf_suffix_type
-s390_lit_suffix (str_p, exp_p, suffix)
- char **str_p;
- expressionS *exp_p;
- elf_suffix_type suffix;
+s390_lit_suffix (char **str_p, expressionS *exp_p, elf_suffix_type suffix)
{
bfd_reloc_code_real_type reloc;
char tmp_name[64];
/* Like normal .long/.short/.word, except support @got, etc.
clobbers input_line_pointer, checks end-of-line. */
static void
-s390_elf_cons (nbytes)
- register int nbytes; /* 1=.byte, 2=.word, 4=.long */
+s390_elf_cons (int nbytes /* 1=.byte, 2=.word, 4=.long */)
{
expressionS exp;
elf_suffix_type suffix;
/* This routine is called for each instruction to be assembled. */
static char *
-md_gather_operands (str, insn, opcode)
- char *str;
- unsigned char *insn;
- const struct s390_opcode *opcode;
+md_gather_operands (char *str,
+ unsigned char *insn,
+ const struct s390_opcode *opcode)
{
struct s390_fixup fixups[MAX_INSN_FIXUPS];
const struct s390_operand *operand;
if (ex.X_op == O_illegal)
as_bad (_("illegal operand"));
else if (ex.X_op == O_absent)
- as_bad (_("missing operand"));
+ {
+ /* 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"));
+ }
else if (ex.X_op == O_register || ex.X_op == O_constant)
{
s390_lit_suffix (&str, &ex, ELF_SUFFIX_NONE);
if ((operand->flags & S390_OPERAND_INDEX)
&& ex.X_add_number == 0
&& warn_areg_zero)
- 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
&& warn_areg_zero)
- 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);
}
}
/* This routine is called for each instruction to be assembled. */
void
-md_assemble (str)
- char *str;
+md_assemble (char *str)
{
const struct s390_opcode *opcode;
unsigned char insn[6];
}
else if (!(opcode->modes & current_mode_mask))
{
- as_bad ("Opcode %s not available in this mode", str);
+ as_bad (_("Opcode %s not available in this mode"), str);
return;
}
memcpy (insn, opcode->opcode, sizeof (insn));
#endif
void
-s390_bss (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s390_bss (int ignore ATTRIBUTE_UNUSED)
{
/* We don't support putting frags in the BSS segment, we fake it
by marking in_bss, then looking at s_skip for clues. */
/* Pseudo-op handling. */
void
-s390_insn (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s390_insn (int ignore ATTRIBUTE_UNUSED)
{
expressionS exp;
const struct s390_opcode *opformat;
pseudo-op, but it can also take a single ASCII string. */
static void
-s390_byte (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s390_byte (int ignore ATTRIBUTE_UNUSED)
{
if (*input_line_pointer != '\"')
{
@lit suffix. */
static void
-s390_literals (ignore)
- int ignore ATTRIBUTE_UNUSED;
+s390_literals (int ignore ATTRIBUTE_UNUSED)
{
struct s390_lpe *lpe;
lpe_count = 0;
}
-/* Turn a string in input_line_pointer into a floating point constant
- of type type, and store the appropriate bytes in *litp. The number
- of LITTLENUMS emitted is stored in *sizep . An error message is
- returned, or NULL on OK. */
-
char *
-md_atof (type, litp, sizep)
- int type;
- char *litp;
- int *sizep;
+md_atof (int type, char *litp, int *sizep)
{
- int prec;
- LITTLENUM_TYPE words[4];
- char *t;
- int i;
-
- switch (type)
- {
- case 'f':
- prec = 2;
- break;
-
- case 'd':
- prec = 4;
- break;
-
- default:
- *sizep = 0;
- return "bad call to md_atof";
- }
-
- t = atof_ieee (input_line_pointer, type, words);
- if (t)
- input_line_pointer = t;
-
- *sizep = prec * 2;
-
- for (i = 0; i < prec; i++)
- {
- md_number_to_chars (litp, (valueT) words[i], 2);
- litp += 2;
- }
-
- return NULL;
+ return ieee_md_atof (type, litp, sizep, TRUE);
}
/* Align a section (I don't know why this is machine dependent). */
valueT
-md_section_align (seg, addr)
- asection *seg;
- valueT addr;
+md_section_align (asection *seg, valueT addr)
{
int align = bfd_get_section_alignment (stdoutput, seg);
/* We don't have any form of relaxing. */
int
-md_estimate_size_before_relax (fragp, seg)
- fragS *fragp ATTRIBUTE_UNUSED;
- asection *seg ATTRIBUTE_UNUSED;
+md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
+ asection *seg ATTRIBUTE_UNUSED)
{
abort ();
return 0;
/* Convert a machine dependent frag. We never generate these. */
void
-md_convert_frag (abfd, sec, fragp)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *sec ATTRIBUTE_UNUSED;
- fragS *fragp ATTRIBUTE_UNUSED;
+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *sec ATTRIBUTE_UNUSED,
+ fragS *fragp ATTRIBUTE_UNUSED)
{
abort ();
}
symbolS *
-md_undefined_symbol (name)
- char *name;
+md_undefined_symbol (char *name)
{
if (*name == '_' && *(name + 1) == 'G'
&& strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
given a PC relative reloc. */
long
-md_pcrel_from_section (fixp, sec)
- fixS *fixp;
- segT sec ATTRIBUTE_UNUSED;
+md_pcrel_from_section (fixS *fixp, segT sec ATTRIBUTE_UNUSED)
{
return fixp->fx_frag->fr_address + fixp->fx_where;
}
to make sure that the dynamic relocations are done correctly, so in
some cases we force the original symbol to be used. */
int
-tc_s390_fix_adjustable (fixP)
- fixS *fixP;
+tc_s390_fix_adjustable (fixS *fixP)
{
/* Don't adjust references to merge sections. */
if ((S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0)
/* Return true if we must always emit a reloc for a type and false if
there is some hope of resolving it at assembly time. */
int
-tc_s390_force_relocation (fixp)
- struct fix *fixp;
+tc_s390_force_relocation (struct fix *fixp)
{
/* Ensure we emit a relocation for every reference to the global
offset table or to the procedure link table. */
fixup. */
void
-md_apply_fix (fixP, valP, seg)
- fixS *fixP;
- valueT *valP;
- segT seg ATTRIBUTE_UNUSED;
+md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
char *where;
valueT value = *valP;
if (fixP->fx_subsy != NULL)
as_bad_where (fixP->fx_file, fixP->fx_line,
- "cannot emit relocation %s against subsy symbol %s",
+ _("cannot emit relocation %s against subsy symbol %s"),
bfd_get_reloc_code_name (fixP->fx_r_type),
S_GET_NAME (fixP->fx_subsy));
case BFD_RELOC_16_GOTOFF:
if (fixP->fx_pcrel)
as_bad_where (fixP->fx_file, fixP->fx_line,
- "cannot emit PC relative %s relocation%s%s",
+ _("cannot emit PC relative %s relocation%s%s"),
bfd_get_reloc_code_name (fixP->fx_r_type),
fixP->fx_addsy != NULL ? " against " : "",
(fixP->fx_addsy != NULL
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);
+ as_fatal (_("Gas failure, reloc type %s\n"), reloc_name);
else
- fprintf (stderr, "Gas failure, reloc type #%i\n", fixP->fx_r_type);
- fflush (stderr);
- abort ();
+ as_fatal (_("Gas failure, reloc type #%i\n"), fixP->fx_r_type);
}
}
/* Generate a reloc for a fixup. */
arelent *
-tc_gen_reloc (seg, fixp)
- asection *seg ATTRIBUTE_UNUSED;
- fixS *fixp;
+tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
{
bfd_reloc_code_real_type code;
arelent *reloc;
bfd_get_reloc_code_name (code));
/* Set howto to a garbage value so that we can keep going. */
reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
- assert (reloc->howto != NULL);
+ gas_assert (reloc->howto != NULL);
}
reloc->addend = fixp->fx_offset;
}
void
-s390_cfi_frame_initial_instructions ()
+s390_cfi_frame_initial_instructions (void)
{
cfi_add_CFA_def_cfa (15, s390_arch_size == 64 ? 160 : 96);
}