diff mbox

Support -mcpu=native on Solaris/SPARC

Message ID yddzkjt5jf0.fsf@manam.CeBiTec.Uni-Bielefeld.DE
State New
Headers show

Commit Message

Rainer Orth Aug. 1, 2011, 1:51 p.m. UTC
Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:

> This is a first cut at supporting -mcpu=native/-mtune=native on
> Solaris/SPARC.  Unlike it's Tru64 UNIX/Alpha and IRIX/MIPS (to be
> submitted soon) counterparts, it's a bit more involved:
>
> * There's no support for -mcpu=native in the SPARC port yet.
>
> * Access to the %ver register is privileged, so we need OS interfaces to
>   access the information.  I couldn't find anything in libc.  While the
>   AT_SUN_CPU file from <sys/auxv.h> might fill the bill, it isn't
>   actually set according to pargs -x.
>
>   There seem to be two options: libkstat and libpicl.  The former has
>   the advantage that it's a tad better documented and talks directly to
>   the kernel, while the latter needs picld, which seems overkill.  Both
>   are present in Solaris 8, though.
>
>   I prefer the cpu_info:::brand kstat over cpu_info:::implementation:
>
>   The former looks like (from kstat -p cpu_info:::brand):
>
>   cpu_info:0:cpu_info0:brand      UltraSPARC-T2
>
>   compared to
>
>   cpu_info:0:cpu_info0:implementation     UltraSPARC-T2 (chipid 0, clock 1165 MHz)
>
>   but brand was only introduced in Solaris 10.  Before that, only
>   implementation existed with this contents:
>
>   cpu_info:0:cpu_info0:implementation     UltraSPARC-IIIi
>
> * Unlike IRIX and Tru64 UNIX, where the respective interfaces return a
>   numeric identifier for the cpu type from a finite range, on SPARC we
>   get string names, and I'm having some trouble determining the complete
>   set.  The patch below is based on what I've found so far, but
>   certainly needs to be augmented for sun4m cpus which I don't have any
>   longer.
>
> * The requirement to link the drivers with an additional library
>   (-lkstat) prompted me to introduce GCC_EXTRA_LIBS.  I didn't want to
>   link the backends with -lkstat since they don't need it.  The build
>   maintainers may not like the way this was done, though.
>
> * Right now, this is Solaris-only since I have no idea what
>   /proc/cpuinfo on Linux/SPARC contains.
>
> With all those caveats, the patch has been run through a C-only
> non-bootstrap build on sparc-sun-solaris2.11 so far.
> -mcpu=native/-mtune=native seem to work as expected, though I'll have to
> broaden the range of OS versions tested.  I'm seeing tons of testsuite

Here's an updated version of the patch, containing two changes:

* Solaris 8 doesn't support KSTAT_DATA_STRING.

* I've updated the list of known cpu types, based on the
  /platform/sun4?/kernel/cpu{, /sparcv9} entries found in Solaris 8, 9,
  10 and 11.  It seems that the vendor field sometimes present there
  (SUNW, TI, Ross, ...) is consistently absent in the kstat output.
  While I could confirm this on all sun4u/sun4v system we have, I don't
  have access to sun4m machines any longer, so it's just a guess.

Bootstrapped without regressions no sparc-sun-solaris2.{8, 9, 10, 11}
without regressions (Solaris 8 bootstrap still running), -mcpu is
correctly detected everywhere.

Ok for mainline?

Thanks.
	Rainer


2011-07-27  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	gcc:
	* config/sparc/driver-sparc.c: New file.
	* config/sparc/x-sparc: New file.
	* config.host: Use driver-sparc.o, sparc/x-sparc on
	sparc*-*-solaris2*.
	* config/sparc/sparc.opt (native): New value for enum
	processor_type.
	* config/sparc/sparc-opts.h (PROCESSOR_NATIVE): Declare.
	* config/sparc/sparc.c (sparc_option_override): Abort if
	PROCESSOR_NATIVE gets here.
	* config/sparc/sol2.h [__sparc__] (host_detect_local_cpu): Declare.
	(EXTRA_SPEC_FUNCTIONS, MCPU_MTUNE_NATIVE_SPECS,
	DRIVER_SELF_SPECS): Define.
	* configure.ac (EXTRA_GCC_LIBS): Check for libkstat.
	Substitute result.
	* configure: Regenerate.
	* Makefile.in (EXTRA_GCC_LIBS): Set.
	(xgcc$(exeext)): Add $(EXTRA_GCC_LIBS).
	(cpp$(exeext)): Likewise.

	gcc/cp:
	* Make-lang.in (g++$(exeext)): Add $(EXTRA_GCC_LIBS).

	gcc/fortran:
	* Make-lang.in (gfortran$(exeext)): Add $(EXTRA_GCC_LIBS).

	gcc/go:
	* Make-lang.in (gccgo$(exeext)): Add $(EXTRA_GCC_LIBS).

	gcc/java:
	* Make-lang.in ($(XGCJ)$(exeext)): Add $(EXTRA_GCC_LIBS).

Comments

Paolo Bonzini Aug. 1, 2011, 1:55 p.m. UTC | #1
On 08/01/2011 03:51 PM, Rainer Orth wrote:
> Here's an updated version of the patch, containing two changes:
>
> * Solaris 8 doesn't support KSTAT_DATA_STRING.
>
> * I've updated the list of known cpu types, based on the
>    /platform/sun4?/kernel/cpu{, /sparcv9} entries found in Solaris 8, 9,
>    10 and 11.  It seems that the vendor field sometimes present there
>    (SUNW, TI, Ross, ...) is consistently absent in the kstat output.
>    While I could confirm this on all sun4u/sun4v system we have, I don't
>    have access to sun4m machines any longer, so it's just a guess.
>
> Bootstrapped without regressions no sparc-sun-solaris2.{8, 9, 10, 11}
> without regressions (Solaris 8 bootstrap still running), -mcpu is
> correctly detected everywhere.
>
> Ok for mainline?

Build parts are ok.

Paolo
Eric Botcazou Aug. 7, 2011, 8:32 p.m. UTC | #2
> 2011-07-27  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
>
> 	gcc:
> 	* config/sparc/driver-sparc.c: New file.
> 	* config/sparc/x-sparc: New file.
> 	* config.host: Use driver-sparc.o, sparc/x-sparc on
> 	sparc*-*-solaris2*.
> 	* config/sparc/sparc.opt (native): New value for enum
> 	processor_type.
> 	* config/sparc/sparc-opts.h (PROCESSOR_NATIVE): Declare.
> 	* config/sparc/sparc.c (sparc_option_override): Abort if
> 	PROCESSOR_NATIVE gets here.
> 	* config/sparc/sol2.h [__sparc__] (host_detect_local_cpu): Declare.
> 	(EXTRA_SPEC_FUNCTIONS, MCPU_MTUNE_NATIVE_SPECS,
> 	DRIVER_SELF_SPECS): Define.
> 	* configure.ac (EXTRA_GCC_LIBS): Check for libkstat.
> 	Substitute result.
> 	* configure: Regenerate.
> 	* Makefile.in (EXTRA_GCC_LIBS): Set.
> 	(xgcc$(exeext)): Add $(EXTRA_GCC_LIBS).
> 	(cpp$(exeext)): Likewise.

OK if you document the new value in doc/invoke.texi, thanks in advance.
diff mbox

Patch

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -723,6 +723,9 @@  EXTRA_OBJS = @extra_objs@
 # the gcc driver.
 EXTRA_GCC_OBJS =@extra_gcc_objs@
 
+# List of extra libraries that should be linked with the gcc driver.
+EXTRA_GCC_LIBS = @EXTRA_GCC_LIBS@
+
 # List of additional header files to install.
 EXTRA_HEADERS =@extra_headers_list@
 
@@ -1828,7 +1831,8 @@  libcommon.a: $(OBJS-libcommon)
 xgcc$(exeext): $(GCC_OBJS) gccspec.o libcommon-target.a $(LIBDEPS) \
 	$(EXTRA_GCC_OBJS)
 	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) \
-	  gccspec.o $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBS)
+	  gccspec.o $(EXTRA_GCC_OBJS) libcommon-target.a \
+	  $(EXTRA_GCC_LIBS) $(LIBS)
 
 # cpp is to cpp0 as gcc is to cc1.
 # The only difference from xgcc is that it's linked with cppspec.o
@@ -1836,7 +1840,8 @@  xgcc$(exeext): $(GCC_OBJS) gccspec.o lib
 cpp$(exeext): $(GCC_OBJS) cppspec.o libcommon-target.a $(LIBDEPS) \
 	$(EXTRA_GCC_OBJS)
 	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) \
-	  cppspec.o $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBS)
+	  cppspec.o $(EXTRA_GCC_OBJS) libcommon-target.a \
+	  $(EXTRA_GCC_LIBS) $(LIBS)
 
 # Dump a specs file to make -B./ read these specs over installed ones.
 $(SPECS): xgcc$(exeext)
diff --git a/gcc/config.host b/gcc/config.host
--- a/gcc/config.host
+++ b/gcc/config.host
@@ -157,6 +157,14 @@  case ${host} in
 	;;
     esac
     ;;
+  sparc*-*-solaris2*)
+    case ${target} in
+      sparc*-*-solaris2*)
+	host_extra_gcc_objs="driver-sparc.o"
+	host_xmake_file="${host_xmake_file} sparc/x-sparc"
+	;;
+    esac
+    ;;
 esac
 
 # Machine-specific settings.
diff --git a/gcc/config/sparc/driver-sparc.c b/gcc/config/sparc/driver-sparc.c
new file mode 100644
--- /dev/null
+++ b/gcc/config/sparc/driver-sparc.c
@@ -0,0 +1,158 @@ 
+/* Subroutines for the gcc driver.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+
+static const struct cpu_names {
+  const char *const name;
+  const char *const cpu;
+} cpu_names[] = {
+#if defined __sun__ && defined __svr4__
+  { "TMS390S10",	"supersparc" },	/* Texas Instruments microSPARC I */
+  { "TMS390Z50",	"supersparc" },	/* Texas Instruments SuperSPARC I */
+  { "TMS390Z55",	"supersparc" },	/* Texas Instruments
+					   SuperSPARC I with SuperCache */
+  { "MB86904",		"supersparc" },	/* Fujitsu microSPARC II */
+  { "MB86907",		"supersparc" },	/* Fujitsu TurboSPARC */
+  { "RT623",		"hypersparc" },	/* Ross hyperSPARC */
+  { "RT625",		"hypersparc" },
+  { "RT626",		"hypersparc" },
+  { "UltraSPARC-I",	"ultrasparc" },
+  { "UltraSPARC-II",	"ultrasparc" },
+  { "UltraSPARC-IIe",	"ultrasparc" },
+  { "UltraSPARC-IIi",	"ultrasparc" },
+  { "SPARC64-III",	"ultrasparc" },
+  { "SPARC64-IV",	"ultrasparc" },
+  { "UltraSPARC-III",	"ultrasparc3" },
+  { "UltraSPARC-III+",	"ultrasparc3" },
+  { "UltraSPARC-IIIi",	"ultrasparc3" },
+  { "UltraSPARC-IIIi+",	"ultrasparc3" },
+  { "UltraSPARC-IV",	"ultrasparc3" },
+  { "UltraSPARC-IV+",	"ultrasparc3" },
+  { "SPARC64-V",	"ultrasparc3" },
+  { "SPARC64-VI",	"ultrasparc3" },
+  { "SPARC64-VII",	"ultrasparc3" },
+  { "UltraSPARC-T1",	"niagara" },
+  { "UltraSPARC-T2",	"niagara2" },
+  { "UltraSPARC-T2",	"niagara2" },
+  { "UltraSPARC-T2+",	"niagara2" },
+  { "SPARC-T3",		"niagara2" },
+  { "SPARC-T4",		"niagara2" },
+#else
+  /* FIXME: Provide Linux/SPARC values.  */
+#endif
+  { NULL,	NULL }
+  };
+
+#if defined __sun__ && defined __svr4__
+#include <kstat.h>
+#endif
+
+/* This will be called by the spec parser in gcc.c when it sees
+   a %:local_cpu_detect(args) construct.  Currently it will be called
+   with either "cpu" or "tune" as argument depending on if -mcpu=native
+   or -mtune=native is to be substituted.
+
+   It returns a string containing new command line parameters to be
+   put at the place of the above two options, depending on what CPU
+   this is executed.  E.g. "-mcpu=ultrasparc3" on an UltraSPARC III for
+   -mcpu=native.  If the routine can't detect a known processor,
+   the -mcpu or -mtune option is discarded.
+
+   ARGC and ARGV are set depending on the actual arguments given
+   in the spec.  */
+const char *
+host_detect_local_cpu (int argc, const char **argv)
+{
+  const char *cpu = NULL;
+#if defined __sun__ && defined __svr4__
+  char *buf = NULL;
+  kstat_ctl_t *kc;
+  kstat_t *ksp;
+  kstat_named_t *brand = NULL;
+#else
+  char buf[128];
+  FILE *f;
+#endif
+  int i;
+
+  if (argc < 1)
+    return NULL;
+
+  if (strcmp (argv[0], "cpu") && strcmp (argv[0], "tune"))
+    return NULL;
+
+#if defined __sun__ && defined __svr4__
+  kc = kstat_open ();
+  if (kc != NULL)
+    {
+      ksp = kstat_lookup (kc, CONST_CAST2 (char *, const char *, "cpu_info"),
+			  -1, NULL);
+      if (ksp != NULL
+	  && kstat_read (kc, ksp, NULL) != -1
+	  && ksp->ks_type == KSTAT_TYPE_NAMED)
+	brand = (kstat_named_t *)
+	  kstat_data_lookup (ksp, CONST_CAST2 (char *, const char *, "brand"));
+      /* "brand" was only introduced in Solaris 10.  */
+      if (brand == NULL)
+	  brand = (kstat_named_t *)
+	    kstat_data_lookup (ksp, CONST_CAST2 (char *, const char *,
+						 "implementation"));
+      /* KSTAT_DATA_STRING was introduced in Solaris 9.  */
+#ifdef KSTAT_DATA_STRING
+      if (brand != NULL && brand->data_type == KSTAT_DATA_STRING)
+	buf = KSTAT_NAMED_STR_PTR (brand);
+#else
+      if (brand != NULL && brand->data_type == KSTAT_DATA_CHAR)
+	buf = brand->value.c;
+#endif
+    }
+  kstat_close (kc);
+
+  for (i = 0; cpu_names[i].name != NULL; i++)
+    if (strcmp (buf, cpu_names[i].name) == 0)
+      cpu = cpu_names[i].cpu;
+#else
+  f = fopen ("/proc/cpuinfo", "r");
+  if (f == NULL)
+    return NULL;
+
+  while (fgets (buf, sizeof (buf), f) != NULL)
+    if (strncmp (buf, "cpu model", sizeof ("cpu model") - 1) == 0)
+      {
+        for (i = 0; cpu_names [i].name; i++)
+          if (strstr (buf, cpu_names [i].name) != NULL)
+	    {
+	      cpu = cpu_names [i].cpu;
+	      break;
+	    }
+	break;
+      }
+
+  fclose (f);
+#endif
+
+  if (cpu == NULL)
+    return NULL;
+
+  return concat ("-m", argv[0], "=", cpu, NULL);
+}
diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h
--- a/gcc/config/sparc/sol2.h
+++ b/gcc/config/sparc/sol2.h
@@ -157,6 +157,22 @@  along with GCC; see the file COPYING3.  
 %{!m32:%{!m64:%(cpp_arch_default)}} \
 "
 
+/* -mcpu=native handling only makes sense with compiler running on
+   a SPARC chip.  */
+#if defined(__sparc__)
+extern const char *host_detect_local_cpu (int argc, const char **argv);
+# define EXTRA_SPEC_FUNCTIONS						\
+  { "local_cpu_detect", host_detect_local_cpu },
+
+# define MCPU_MTUNE_NATIVE_SPECS					\
+   " %{mcpu=native:%<mcpu=native %:local_cpu_detect(cpu)}"		\
+   " %{mtune=native:%<mtune=native %:local_cpu_detect(tune)}"
+#else
+# define MCPU_MTUNE_NATIVE_SPECS ""
+#endif
+
+#define DRIVER_SELF_SPECS MCPU_MTUNE_NATIVE_SPECS
+
 #undef	CC1_SPEC
 #if DEFAULT_ARCH32_P
 #define CC1_SPEC "\
diff --git a/gcc/config/sparc/sparc-opts.h b/gcc/config/sparc/sparc-opts.h
--- a/gcc/config/sparc/sparc-opts.h
+++ b/gcc/config/sparc/sparc-opts.h
@@ -41,7 +41,8 @@  enum processor_type {
   PROCESSOR_ULTRASPARC,
   PROCESSOR_ULTRASPARC3,
   PROCESSOR_NIAGARA,
-  PROCESSOR_NIAGARA2
+  PROCESSOR_NIAGARA2,
+  PROCESSOR_NATIVE
 };
 
 #endif
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -911,6 +911,8 @@  sparc_option_override (void)
     case PROCESSOR_NIAGARA2:
       sparc_costs = &niagara2_costs;
       break;
+    case PROCESSOR_NATIVE:
+      gcc_unreachable ();
     };
 
 #ifdef TARGET_DEFAULT_LONG_DOUBLE_128
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -101,6 +101,9 @@  Enum
 Name(sparc_processor_type) Type(enum processor_type)
 
 EnumValue
+Enum(sparc_processor_type) String(native) Value(PROCESSOR_NATIVE) DriverOnly
+
+EnumValue
 Enum(sparc_processor_type) String(v7) Value(PROCESSOR_V7)
 
 EnumValue
diff --git a/gcc/config/sparc/x-sparc b/gcc/config/sparc/x-sparc
new file mode 100644
--- /dev/null
+++ b/gcc/config/sparc/x-sparc
@@ -0,0 +1,3 @@ 
+driver-sparc.o: $(srcdir)/config/sparc/driver-sparc.c \
+  $(CONFIG_H) $(SYSTEM_H)
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/configure.ac b/gcc/configure.ac
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -970,6 +970,14 @@  GNAT_LIBEXC="$LIBS"
 LIBS="$save_LIBS"
 AC_SUBST(GNAT_LIBEXC)
 
+# To support -mcpu=native on Solaris/SPARC, we need libkstat.
+save_LIBS="$LIBS"
+LIBS=
+AC_SEARCH_LIBS(kstat_open, kstat)
+EXTRA_GCC_LIBS="$LIBS"
+LIBS="$save_LIBS"
+AC_SUBST(EXTRA_GCC_LIBS)
+
 # Some systems put ldexp and frexp in libm instead of libc; assume
 # they're both in the same place.  jcf-dump needs them.
 save_LIBS="$LIBS"
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -63,7 +63,8 @@  g++spec.o: $(srcdir)/cp/g++spec.c $(SYST
 GXX_OBJS = $(GCC_OBJS) g++spec.o
 g++$(exeext): $(GXX_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS)
 	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
-	  $(GXX_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBS)
+	  $(GXX_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \
+	  $(EXTRA_GCC_LIBS) $(LIBS)
 
 # Create a version of the g++ driver which calls the cross-compiler.
 g++-cross$(exeext): g++$(exeext)
diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in
--- a/gcc/fortran/Make-lang.in
+++ b/gcc/fortran/Make-lang.in
@@ -88,7 +88,8 @@  GFORTRAN_D_OBJS = $(GCC_OBJS) gfortransp
 gfortran$(exeext): $(GFORTRAN_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \
 	$(LIBDEPS)
 	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
-	  $(GFORTRAN_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBS)
+	  $(GFORTRAN_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \
+	  $(EXTRA_GCC_LIBS) $(LIBS)
 
 # Create a version of the gfortran driver which calls the cross-compiler.
 gfortran-cross$(exeext): gfortran$(exeext)
diff --git a/gcc/go/Make-lang.in b/gcc/go/Make-lang.in
--- a/gcc/go/Make-lang.in
+++ b/gcc/go/Make-lang.in
@@ -39,7 +39,8 @@  gospec.o: $(srcdir)/go/gospec.c $(SYSTEM
 GCCGO_OBJS = $(GCC_OBJS) gospec.o
 gccgo$(exeext): $(GCCGO_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS)
 	$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
-	  $(GCCGO_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBS)
+	  $(GCCGO_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a \
+	  $(EXTRA_GCC_LIBS) $(LIBS)
 
 # Use strict warnings.
 go-warn = $(STRICT_WARN)
diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in
--- a/gcc/java/Make-lang.in
+++ b/gcc/java/Make-lang.in
@@ -66,7 +66,8 @@  jvspec.o: $(srcdir)/java/jvspec.c $(SYST
 $(XGCJ)$(exeext): $(GCC_OBJS) jvspec.o java/jcf-path.o \
 	   libcommon-target.a $(LIBDEPS) $(EXTRA_GCC_OBJS)
 	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) \
-	  jvspec.o java/jcf-path.o $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBS)
+	  jvspec.o java/jcf-path.o $(EXTRA_GCC_OBJS) libcommon-target.a \
+	  $(EXTRA_GCC_LIBS) $(LIBS)
 
 # Create a version of the $(XGCJ) driver which calls the cross-compiler.
 $(XGCJ)-cross$(exeext): $(XGCJ)$(exeext)