forked from Imagelibrary/binutils-gdb
2011-04-14 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* config/tc-s390.c (s390_machine): New prototype. (md_pseudo_table): New pseudo-op .machine. (s390_opcode_hash): Initialize to NULL. (s390_parse_cpu): New function. (md_parse_option): Use s390_parse_cpu. (s390_setup_opcodes): New function. (md_begin): Use s390_setup_opcodes. (s390_machine): New hook handling the new .machine pseudo. * doc/c-s390.texi: Document the new pseudo op .machine. 2011-04-14 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> * gas/s390/zarch-machine.s: New testcase. * gas/s390/zarch-machine.d: New testcase output. * gas/s390/s390.exp: Execute the new testcase.
This commit is contained in:
@@ -1,3 +1,16 @@
|
||||
2011-04-14 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
|
||||
|
||||
* config/tc-s390.c (s390_machine): New prototype.
|
||||
(md_pseudo_table): New pseudo-op .machine.
|
||||
(s390_opcode_hash): Initialize to NULL.
|
||||
(s390_parse_cpu): New function.
|
||||
(md_parse_option): Use s390_parse_cpu.
|
||||
(s390_setup_opcodes): New function.
|
||||
(md_begin): Use s390_setup_opcodes.
|
||||
(s390_machine): New hook handling the new .machine pseudo.
|
||||
|
||||
* doc/c-s390.texi: Document the new pseudo op .machine.
|
||||
|
||||
2011-04-12 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* config/tc-i386.c (i386_mach): Start error message with lower
|
||||
|
||||
@@ -85,6 +85,7 @@ static void s390_elf_cons (int);
|
||||
static void s390_bss (int);
|
||||
static void s390_insn (int);
|
||||
static void s390_literals (int);
|
||||
static void s390_machine (int);
|
||||
|
||||
const pseudo_typeS md_pseudo_table[] =
|
||||
{
|
||||
@@ -99,6 +100,7 @@ const pseudo_typeS md_pseudo_table[] =
|
||||
{ "quad", s390_elf_cons, 8 },
|
||||
{ "ltorg", s390_literals, 0 },
|
||||
{ "string", stringer, 8 + 1 },
|
||||
{ "machine", s390_machine, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
@@ -293,7 +295,7 @@ register_name (expressionS *expressionP)
|
||||
static struct hash_control *s390_opformat_hash;
|
||||
|
||||
/* Opcode hash table. */
|
||||
static struct hash_control *s390_opcode_hash;
|
||||
static struct hash_control *s390_opcode_hash = NULL;
|
||||
|
||||
/* Flags to set in the elf header */
|
||||
static flagword s390_flags = 0;
|
||||
@@ -350,6 +352,35 @@ s390_target_format (void)
|
||||
return s390_arch_size == 64 ? "elf64-s390" : "elf32-s390";
|
||||
}
|
||||
|
||||
/* Map a CPU string as given with -march= or .machine to the
|
||||
respective enum s390_opcode_cpu_val value. 0xffffffff is returned
|
||||
in case of an error. */
|
||||
|
||||
static unsigned int
|
||||
s390_parse_cpu (char *arg)
|
||||
{
|
||||
if (strcmp (arg, "g5") == 0)
|
||||
return S390_OPCODE_G5;
|
||||
else if (strcmp (arg, "g6") == 0)
|
||||
return S390_OPCODE_G6;
|
||||
else if (strcmp (arg, "z900") == 0)
|
||||
return S390_OPCODE_Z900;
|
||||
else if (strcmp (arg, "z990") == 0)
|
||||
return S390_OPCODE_Z990;
|
||||
else if (strcmp (arg, "z9-109") == 0)
|
||||
return S390_OPCODE_Z9_109;
|
||||
else if (strcmp (arg, "z9-ec") == 0)
|
||||
return S390_OPCODE_Z9_EC;
|
||||
else if (strcmp (arg, "z10") == 0)
|
||||
return S390_OPCODE_Z10;
|
||||
else if (strcmp (arg, "z196") == 0)
|
||||
return S390_OPCODE_Z196;
|
||||
else if (strcmp (arg, "all") == 0)
|
||||
return S390_OPCODE_MAXCPU - 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
md_parse_option (int c, char *arg)
|
||||
{
|
||||
@@ -382,25 +413,9 @@ md_parse_option (int c, char *arg)
|
||||
|
||||
else if (arg != NULL && strncmp (arg, "arch=", 5) == 0)
|
||||
{
|
||||
if (strcmp (arg + 5, "g5") == 0)
|
||||
current_cpu = S390_OPCODE_G5;
|
||||
else if (strcmp (arg + 5, "g6") == 0)
|
||||
current_cpu = S390_OPCODE_G6;
|
||||
else if (strcmp (arg + 5, "z900") == 0)
|
||||
current_cpu = S390_OPCODE_Z900;
|
||||
else if (strcmp (arg + 5, "z990") == 0)
|
||||
current_cpu = S390_OPCODE_Z990;
|
||||
else if (strcmp (arg + 5, "z9-109") == 0)
|
||||
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 if (strcmp (arg + 5, "z196") == 0)
|
||||
current_cpu = S390_OPCODE_Z196;
|
||||
else if (strcmp (arg + 5, "all") == 0)
|
||||
current_cpu = S390_OPCODE_MAXCPU - 1;
|
||||
else
|
||||
current_cpu = s390_parse_cpu (arg + 5);
|
||||
|
||||
if (current_cpu == (unsigned int)-1)
|
||||
{
|
||||
as_bad (_("invalid switch -m%s"), arg);
|
||||
return 0;
|
||||
@@ -456,6 +471,53 @@ md_show_usage (FILE *stream)
|
||||
-Qy, -Qn ignored\n"));
|
||||
}
|
||||
|
||||
/* Generate the hash table mapping mnemonics to struct s390_opcode.
|
||||
This table is built at startup and whenever the CPU level is
|
||||
changed using .machine. */
|
||||
|
||||
static void
|
||||
s390_setup_opcodes (void)
|
||||
{
|
||||
register const struct s390_opcode *op;
|
||||
const struct s390_opcode *op_end;
|
||||
bfd_boolean dup_insn = FALSE;
|
||||
const char *retval;
|
||||
|
||||
if (s390_opcode_hash != NULL)
|
||||
hash_die (s390_opcode_hash);
|
||||
|
||||
/* Insert the opcodes into a hash table. */
|
||||
s390_opcode_hash = hash_new ();
|
||||
|
||||
op_end = s390_opcodes + s390_num_opcodes;
|
||||
for (op = s390_opcodes; op < op_end; op++)
|
||||
{
|
||||
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++;
|
||||
}
|
||||
|
||||
if (op->min_cpu <= current_cpu && (op->modes & current_mode_mask))
|
||||
{
|
||||
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)
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* This function is called when the assembler starts up. It is called
|
||||
after the options have been parsed and the output file has been
|
||||
opened. */
|
||||
@@ -493,41 +555,11 @@ md_begin (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert the opcodes into a hash table. */
|
||||
s390_opcode_hash = hash_new ();
|
||||
|
||||
op_end = s390_opcodes + s390_num_opcodes;
|
||||
for (op = s390_opcodes; op < op_end; op++)
|
||||
{
|
||||
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++;
|
||||
}
|
||||
|
||||
if (op->min_cpu <= current_cpu && (op->modes & current_mode_mask))
|
||||
{
|
||||
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)
|
||||
abort ();
|
||||
s390_setup_opcodes ();
|
||||
|
||||
record_alignment (text_section, 2);
|
||||
record_alignment (data_section, 2);
|
||||
record_alignment (bss_section, 2);
|
||||
|
||||
}
|
||||
|
||||
/* Called after all assembly has been done. */
|
||||
@@ -1755,6 +1787,72 @@ s390_literals (int ignore ATTRIBUTE_UNUSED)
|
||||
lpe_count = 0;
|
||||
}
|
||||
|
||||
/* The .machine pseudo op allows to switch to a different CPU level in
|
||||
the asm listing. The current CPU setting can be stored on a stack
|
||||
with .machine push and restored with .machined pop. */
|
||||
|
||||
static void
|
||||
s390_machine (int ignore ATTRIBUTE_UNUSED)
|
||||
{
|
||||
char *cpu_string;
|
||||
#define MAX_HISTORY 100
|
||||
static unsigned int *cpu_history;
|
||||
static int curr_hist;
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
|
||||
if (*input_line_pointer == '"')
|
||||
{
|
||||
int len;
|
||||
cpu_string = demand_copy_C_string (&len);
|
||||
}
|
||||
else
|
||||
{
|
||||
char c;
|
||||
cpu_string = input_line_pointer;
|
||||
c = get_symbol_end ();
|
||||
cpu_string = xstrdup (cpu_string);
|
||||
*input_line_pointer = c;
|
||||
}
|
||||
|
||||
if (cpu_string != NULL)
|
||||
{
|
||||
unsigned int old_cpu = current_cpu;
|
||||
unsigned int new_cpu;
|
||||
char *p;
|
||||
|
||||
for (p = cpu_string; *p != 0; p++)
|
||||
*p = TOLOWER (*p);
|
||||
|
||||
if (strcmp (cpu_string, "push") == 0)
|
||||
{
|
||||
if (cpu_history == NULL)
|
||||
cpu_history = xmalloc (MAX_HISTORY * sizeof (*cpu_history));
|
||||
|
||||
if (curr_hist >= MAX_HISTORY)
|
||||
as_bad (_(".machine stack overflow"));
|
||||
else
|
||||
cpu_history[curr_hist++] = current_cpu;
|
||||
}
|
||||
else if (strcmp (cpu_string, "pop") == 0)
|
||||
{
|
||||
if (curr_hist <= 0)
|
||||
as_bad (_(".machine stack underflow"));
|
||||
else
|
||||
current_cpu = cpu_history[--curr_hist];
|
||||
}
|
||||
else if ((new_cpu = s390_parse_cpu (cpu_string)) != (unsigned int)-1)
|
||||
current_cpu = new_cpu;
|
||||
else
|
||||
as_bad (_("invalid machine `%s'"), cpu_string);
|
||||
|
||||
if (current_cpu != old_cpu)
|
||||
s390_setup_opcodes ();
|
||||
}
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
}
|
||||
|
||||
char *
|
||||
md_atof (int type, char *litp, int *sizep)
|
||||
{
|
||||
|
||||
@@ -862,6 +862,17 @@ ELF extension documentation @samp{ELF Handling For Thread-Local Storage}.
|
||||
@item .ltorg
|
||||
This directive causes the current contents of the literal pool to be
|
||||
dumped to the current location (@ref{s390 Literal Pool Entries}).
|
||||
|
||||
@cindex @code{.machine} directive, s390
|
||||
@item .machine string
|
||||
This directive allows you to change the machine for which code is
|
||||
generated. @code{string} may be any of the @code{-march=} selection
|
||||
options (without the -march=), @code{push}, or @code{pop}.
|
||||
@code{.machine push} saves the currently selected cpu, which may be
|
||||
restored with @code{.machine pop}. Be aware that the cpu string has
|
||||
to be put into double quotes in case it contains characters not
|
||||
appropriate for identifiers. So you have to write @code{"z9-109"}
|
||||
instead of just @code{z9-109}.
|
||||
@end table
|
||||
|
||||
@node s390 Floating Point
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
2011-04-14 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
|
||||
|
||||
* gas/s390/zarch-machine.s: New testcase.
|
||||
* gas/s390/zarch-machine.d: New testcase output.
|
||||
* gas/s390/s390.exp: Execute the new testcase.
|
||||
|
||||
2011-04-13 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* gas/v850/v850e1.s: Add a insn using reg+offset addressing.
|
||||
|
||||
@@ -27,4 +27,5 @@ if [expr [istarget "s390-*-*"] || [istarget "s390x-*-*"]] then {
|
||||
run_dump_test "zarch-z196" "{as -m64} {as -march=z196}"
|
||||
run_dump_test "zarch-reloc" "{as -m64}"
|
||||
run_dump_test "zarch-operands" "{as -m64} {as -march=z9-109}"
|
||||
run_dump_test "zarch-machine" "{as -m64} {as -march=z900}"
|
||||
}
|
||||
|
||||
12
gas/testsuite/gas/s390/zarch-machine.d
Normal file
12
gas/testsuite/gas/s390/zarch-machine.d
Normal file
@@ -0,0 +1,12 @@
|
||||
#name: s390x machine
|
||||
#objdump: -dr
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
.* <foo>:
|
||||
.*: e3 95 af ff 00 08 [ ]*ag %r9,4095\(%r5,%r10\)
|
||||
.*: eb d6 65 b3 01 6a [ ]*asi 5555\(%r6\),-42
|
||||
.*: e3 95 af ff 00 18 [ ]*agf %r9,4095\(%r5,%r10\)
|
||||
.*: 07 07 [ ]*nopr %r7
|
||||
8
gas/testsuite/gas/s390/zarch-machine.s
Normal file
8
gas/testsuite/gas/s390/zarch-machine.s
Normal file
@@ -0,0 +1,8 @@
|
||||
.text
|
||||
foo:
|
||||
ag %r9,4095(%r5,%r10)
|
||||
.machine push
|
||||
.machine z10
|
||||
asi 5555(%r6),-42
|
||||
.machine pop
|
||||
agf %r9,4095(%r5,%r10)
|
||||
Reference in New Issue
Block a user