This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Committed] S/390: Add machinemode pseudo


Hi,

I've committed the attached patch which introduces the .machinemode
pseudo for GAS.  Using that pseudo command it is possible to enable
zarch instructions for portions of the assembler file.

Apart from the obvious parameters esa and zarch there is also
zarch_nohighgprs. ".machinemode zarch" sets the highgprs flag of the
output file.  Using zarch_nohighgprs instead this is suppressed.  This
is helpful when there is a runtime check for the highgprs feature and
the code will anyway only be executed if the kernel provides
'highgprs'. Otherwise the execution of the binary will be prevented on
kernel not having 'highgprs'.

This is necessary for the IFUNC optimized mem* functions added to
glibc when running on a 31 bit kernel.

Bye,

-Andreas-

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.

---
 gas/config/tc-s390.c |  115 ++++++++++++++++++++++++++++++++++++++++++++-------
 gas/doc/c-s390.texi  |   13 +++++
 2 files changed, 114 insertions(+), 14 deletions(-)

Index: binutils/gas/config/tc-s390.c
===================================================================
--- binutils.orig/gas/config/tc-s390.c
+++ binutils/gas/config/tc-s390.c
@@ -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_UNUS
 
 /* 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_UNUSE
   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 *regn
 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: binutils/gas/doc/c-s390.texi
===================================================================
--- binutils.orig/gas/doc/c-s390.texi
+++ binutils/gas/doc/c-s390.texi
@@ -873,6 +873,19 @@ restored with @code{.machine pop}.  Be a
 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]