2012-09-06 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
authorAndreas Krebbel <Andreas.Krebbel@de.ibm.com>
Thu, 6 Sep 2012 08:23:25 +0000 (08:23 +0000)
committerAndreas Krebbel <Andreas.Krebbel@de.ibm.com>
Thu, 6 Sep 2012 08:23:25 +0000 (08:23 +0000)
* config/tc-s390.c (set_highgprs_p): New variable.
(s390_machinemode): New function.
(md_pseudo_table): Add new pseudo command machinemode.
(md_parse_option): Set set_highgprs_p to TRUE if -mzarch was
specified on command line.
(s390_elf_final_processing): Set the highgprs flag in the ELF
header depending on set_highgprs_p.

* doc/c-s390.texi: Document new pseudo machinemode.

gas/ChangeLog
gas/config/tc-s390.c
gas/doc/c-s390.texi

index 59d0d52b5da644296071509e589fdeabf945273b..548ed9e38a440339d04882f54ca5a8d84eacb900 100644 (file)
@@ -1,3 +1,15 @@
+2012-09-06  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
+
+       * config/tc-s390.c (set_highgprs_p): New variable.
+       (s390_machinemode): New function.
+       (md_pseudo_table): Add new pseudo command machinemode.
+       (md_parse_option): Set set_highgprs_p to TRUE if -mzarch was
+       specified on command line.
+       (s390_elf_final_processing): Set the highgprs flag in the ELF
+       header depending on set_highgprs_p.
+
+       * doc/c-s390.texi: Document new pseudo machinemode.
+
 2012-09-05  James Lemke  <jwlemke@codesourcery.com>
 
        * doc/c-ppc.texi: Document -mvle.
index 9bc582faed929b3d2e20df54325cd042f2aefe90..47ec1752f308d2b693c00d30560255c01efd0646 100644 (file)
@@ -44,6 +44,10 @@ static int s390_arch_size = 0;
 static unsigned int current_cpu = S390_OPCODE_MAXCPU - 1;
 static unsigned int current_mode_mask = 0;
 
+/* Set to TRUE if the highgprs flag in the ELF header needs to be set
+   for the output file.  */
+static bfd_boolean set_highgprs_p = FALSE;
+
 /* Whether to use user friendly register names. Default is TRUE.  */
 #ifndef TARGET_REG_NAMES_P
 #define TARGET_REG_NAMES_P TRUE
@@ -86,22 +90,24 @@ static void s390_bss (int);
 static void s390_insn (int);
 static void s390_literals (int);
 static void s390_machine (int);
+static void s390_machinemode (int);
 
 const pseudo_typeS md_pseudo_table[] =
 {
-  { "align", s_align_bytes, 0 },
+  { "align",        s_align_bytes,      0 },
   /* Pseudo-ops which must be defined.  */
-  { "bss",      s390_bss,       0 },
-  { "insn",     s390_insn,      0 },
+  { "bss",          s390_bss,           0 },
+  { "insn",         s390_insn,          0 },
   /* Pseudo-ops which must be overridden.  */
-  { "byte",    s390_byte,      0 },
-  { "short",    s390_elf_cons,  2 },
-  { "long",    s390_elf_cons,  4 },
-  { "quad",     s390_elf_cons,  8 },
-  { "ltorg",    s390_literals,  0 },
-  { "string",   stringer,       8 + 1 },
-  { "machine",  s390_machine,   0 },
-  { NULL,      NULL,           0 }
+  { "byte",        s390_byte,          0 },
+  { "short",        s390_elf_cons,      2 },
+  { "long",        s390_elf_cons,      4 },
+  { "quad",         s390_elf_cons,      8 },
+  { "ltorg",        s390_literals,      0 },
+  { "string",       stringer,           8 + 1 },
+  { "machine",      s390_machine,       0 },
+  { "machinemode",  s390_machinemode,   0 },
+  { NULL,          NULL,               0 }
 };
 
 
@@ -409,7 +415,11 @@ md_parse_option (int c, char *arg)
        current_mode_mask = 1 << S390_OPCODE_ESA;
 
       else if (arg != NULL && strcmp (arg, "zarch") == 0)
-       current_mode_mask = 1 << S390_OPCODE_ZARCH;
+       {
+         if (s390_arch_size == 32)
+           set_highgprs_p = TRUE;
+         current_mode_mask = 1 << S390_OPCODE_ZARCH;
+       }
 
       else if (arg != NULL && strncmp (arg, "arch=", 5) == 0)
        {
@@ -1799,7 +1809,7 @@ s390_literals (int ignore ATTRIBUTE_UNUSED)
 
 /* 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.  */
+   with .machine push and restored with .machine pop.  */
 
 static void
 s390_machine (int ignore ATTRIBUTE_UNUSED)
@@ -1863,6 +1873,83 @@ s390_machine (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
+/* The .machinemode pseudo op allows to switch to a different
+   architecture mode in the asm listing.  The current architecture
+   mode setting can be stored on a stack with .machinemode push and
+   restored with .machinemode pop.  */
+
+static void
+s390_machinemode (int ignore ATTRIBUTE_UNUSED)
+{
+  char *mode_string;
+#define MAX_HISTORY 100
+  static unsigned int *mode_history;
+  static int curr_hist;
+
+  SKIP_WHITESPACE ();
+
+  if (*input_line_pointer == '"')
+    {
+      int len;
+      mode_string = demand_copy_C_string (&len);
+    }
+  else
+    {
+      char c;
+      mode_string = input_line_pointer;
+      c = get_symbol_end ();
+      mode_string = xstrdup (mode_string);
+      *input_line_pointer = c;
+    }
+
+  if (mode_string != NULL)
+    {
+      unsigned int old_mode_mask = current_mode_mask;
+      char *p;
+
+      for (p = mode_string; *p != 0; p++)
+       *p = TOLOWER (*p);
+
+      if (strcmp (mode_string, "push") == 0)
+       {
+         if (mode_history == NULL)
+           mode_history = xmalloc (MAX_HISTORY * sizeof (*mode_history));
+
+         if (curr_hist >= MAX_HISTORY)
+           as_bad (_(".machinemode stack overflow"));
+         else
+           mode_history[curr_hist++] = current_mode_mask;
+       }
+      else if (strcmp (mode_string, "pop") == 0)
+       {
+         if (curr_hist <= 0)
+           as_bad (_(".machinemode stack underflow"));
+         else
+           current_mode_mask = mode_history[--curr_hist];
+       }
+      else
+       {
+         if (strcmp (mode_string, "esa") == 0)
+           current_mode_mask = 1 << S390_OPCODE_ESA;
+         else if (strcmp (mode_string, "zarch") == 0)
+           {
+             if (s390_arch_size == 32)
+               set_highgprs_p = TRUE;
+             current_mode_mask = 1 << S390_OPCODE_ZARCH;
+           }
+         else if (strcmp (mode_string, "zarch_nohighgprs") == 0)
+           current_mode_mask = 1 << S390_OPCODE_ZARCH;
+         else
+           as_bad (_("invalid machine `%s'"), mode_string);
+       }
+
+      if (current_mode_mask != old_mode_mask)
+       s390_setup_opcodes ();
+    }
+
+  demand_empty_rest_of_line ();
+}
+
 char *
 md_atof (int type, char *litp, int *sizep)
 {
@@ -2381,6 +2468,6 @@ tc_s390_regname_to_dw2regnum (char *regname)
 void
 s390_elf_final_processing (void)
 {
-  if (s390_arch_size == 32 && (current_mode_mask & (1 << S390_OPCODE_ZARCH)))
+  if (set_highgprs_p)
     elf_elfheader (stdoutput)->e_flags |= EF_S390_HIGH_GPRS;
 }
index 79713277ca4e8435b3e9cbbbe2afb29b0c1b2b4e..76dc1449c0d21921e1e81f4d19bcc10b8875d190 100644 (file)
@@ -873,6 +873,19 @@ 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}.
+
+@cindex @code{.machinemode} directive, s390
+@item .machinemode string
+This directive allows to change the architecture mode for which code
+is being generated.  @code{string} may be @code{esa}, @code{zarch},
+@code{zarch_nohighgprs}, @code{push}, or @code{pop}.
+@code{.machinemode zarch_nohighgprs} can be used to prevent the
+@code{highgprs} flag from being set in the ELF header of the output
+file.  This is useful in situations where the code is gated with a
+runtime check which makes sure that the code is only executed on
+kernels providing the @code{highgprs} feature.
+@code{.machinemode push} saves the currently selected mode, which may
+be restored with @code{.machinemode pop}.
 @end table
 
 @node s390 Floating Point