aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog13
-rw-r--r--gas/config/tc-s390.c198
-rw-r--r--gas/doc/c-s390.texi11
-rw-r--r--gas/testsuite/ChangeLog6
-rw-r--r--gas/testsuite/gas/s390/s390.exp1
-rw-r--r--gas/testsuite/gas/s390/zarch-machine.d12
-rw-r--r--gas/testsuite/gas/s390/zarch-machine.s8
7 files changed, 199 insertions, 50 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 65bb341..2c7f2f6 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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
diff --git a/gas/config/tc-s390.c b/gas/config/tc-s390.c
index 37c0e4d..8fc66d8 100644
--- a/gas/config/tc-s390.c
+++ b/gas/config/tc-s390.c
@@ -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,42 +471,20 @@ md_show_usage (FILE *stream)
-Qy, -Qn ignored\n"));
}
-/* 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. */
+/* 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. */
-void
-md_begin (void)
+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;
- /* 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."));
-
- s390_cie_data_alignment = -s390_arch_size / 8;
-
- /* Set the ELF flags if desired. */
- if (s390_flags)
- bfd_set_private_flags (stdoutput, s390_flags);
-
- /* Insert the opcode formats into a hash table. */
- s390_opformat_hash = hash_new ();
-
- op_end = s390_opformats + s390_num_opformats;
- for (op = s390_opformats; op < op_end; 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->name);
- dup_insn = TRUE;
- }
- }
+ if (s390_opcode_hash != NULL)
+ hash_die (s390_opcode_hash);
/* Insert the opcodes into a hash table. */
s390_opcode_hash = hash_new ();
@@ -523,11 +516,50 @@ md_begin (void)
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. */
+
+void
+md_begin (void)
+{
+ register const struct s390_opcode *op;
+ const struct s390_opcode *op_end;
+ bfd_boolean dup_insn = FALSE;
+ const char *retval;
+
+ /* 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."));
+
+ s390_cie_data_alignment = -s390_arch_size / 8;
+
+ /* Set the ELF flags if desired. */
+ if (s390_flags)
+ bfd_set_private_flags (stdoutput, s390_flags);
+
+ /* Insert the opcode formats into a hash table. */
+ s390_opformat_hash = hash_new ();
+
+ op_end = s390_opformats + s390_num_opformats;
+ for (op = s390_opformats; op < op_end; 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->name);
+ dup_insn = TRUE;
+ }
+ }
+
+ 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)
{
diff --git a/gas/doc/c-s390.texi b/gas/doc/c-s390.texi
index 0d629f9..7971327 100644
--- a/gas/doc/c-s390.texi
+++ b/gas/doc/c-s390.texi
@@ -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
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index 16abb00..d3492aa 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -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.
diff --git a/gas/testsuite/gas/s390/s390.exp b/gas/testsuite/gas/s390/s390.exp
index ec9805d..dad828a 100644
--- a/gas/testsuite/gas/s390/s390.exp
+++ b/gas/testsuite/gas/s390/s390.exp
@@ -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}"
}
diff --git a/gas/testsuite/gas/s390/zarch-machine.d b/gas/testsuite/gas/s390/zarch-machine.d
new file mode 100644
index 0000000..96a202d
--- /dev/null
+++ b/gas/testsuite/gas/s390/zarch-machine.d
@@ -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
diff --git a/gas/testsuite/gas/s390/zarch-machine.s b/gas/testsuite/gas/s390/zarch-machine.s
new file mode 100644
index 0000000..f40a18c
--- /dev/null
+++ b/gas/testsuite/gas/s390/zarch-machine.s
@@ -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)