2011-04-14 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
authorAndreas Krebbel <Andreas.Krebbel@de.ibm.com>
Thu, 14 Apr 2011 11:11:33 +0000 (11:11 +0000)
committerAndreas Krebbel <Andreas.Krebbel@de.ibm.com>
Thu, 14 Apr 2011 11:11:33 +0000 (11:11 +0000)
* 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.

gas/ChangeLog
gas/config/tc-s390.c
gas/doc/c-s390.texi
gas/testsuite/ChangeLog
gas/testsuite/gas/s390/s390.exp
gas/testsuite/gas/s390/zarch-machine.d [new file with mode: 0644]
gas/testsuite/gas/s390/zarch-machine.s [new file with mode: 0644]

index 65bb3410e9694ab4252a2a5652c3c04a019686f6..2c7f2f68bf7bc2543aad1aa718e99a12c0ba3247 100644 (file)
@@ -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
index 37c0e4d18cff677a301959e28feaa199c2a24881..8fc66d8ebf8f5f3f99395c8a97ab3193979a2625 100644 (file)
@@ -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)
 {
index 0d629f9ae5bdec398309095ab4e98d28f24c2c29..79713277ca4e8435b3e9cbbbe2afb29b0c1b2b4e 100644 (file)
@@ -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
index 16abb0043d4753ee6ea2d46117ac36472d3cec19..d3492aa87cccca142d13314ae3d26862de1849a6 100644 (file)
@@ -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.
index ec9805de5b04cfd4abf130358f2bfd9afbcccd86..dad828a0f26cfd7fb6e25a7aaf610df8c5768cc9 100644 (file)
@@ -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 (file)
index 0000000..96a202d
--- /dev/null
@@ -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 (file)
index 0000000..f40a18c
--- /dev/null
@@ -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)