	* configure.ac (AR_FOR_TARGET, RANLIB_FOR_TARGET): If nvptx-*,
	look for them in the gcc build directory.
	* configure: Regenerate.

	gcc/
	* config.gcc (nvptx-*): Define extra_programs.
	* config/nvptx/nvptx-as.c: New file.
	* config/nvptx/nvptx-ld.c: New file.
	* config/nvptx/t-nvptx (nvptx-ld.o, nvptx-as.o, collect-ld$(exeext),
	as$(exeext), ar$(exeext), ranlib$(exeext): New rules.

Index: git/gcc/config.gcc
===================================================================
--- git.orig/gcc/config.gcc
+++ git/gcc/config.gcc
@@ -2154,6 +2154,7 @@ nios2-*-*)
 nvptx-*)
 	tm_file="${tm_file} newlib-stdint.h"
 	tmake_file="nvptx/t-nvptx"
+	extra_programs="collect-ld\$(exeext) as\$(exeext) ar\$(exeext) ranlib\$(exeext)"
 	;;
 pdp11-*-*)
 	tm_file="${tm_file} newlib-stdint.h"
Index: git/gcc/config/nvptx/nvptx-as.c
===================================================================
--- /dev/null
+++ git/gcc/config/nvptx/nvptx-as.c
@@ -0,0 +1,961 @@
+/* An "assembler" for ptx.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+   Contributed by Nathan Sidwell <nathan@codesourcery.com>
+   Contributed by Bernd Schmidt <bernds@codesourcery.com>
+
+   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/>.  */
+
+/* Munges gcc-generated PTX assembly so that it becomes acceptable for ptxas.
+
+   This is not a complete assembler.  We presume the source is well
+   formed from the compiler and can die horribly if it is not.  */
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <wait.h>
+#include <unistd.h>
+#include <errno.h>
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+#include <obstack.h>
+#define HAVE_DECL_BASENAME 1
+#include <libiberty.h>
+#include <hashtab.h>
+
+#include <list>
+
+static const char *outname = NULL;
+
+static void __attribute__ ((format (printf, 1, 2)))
+fatal_error (const char * cmsgid, ...)
+{
+  va_list ap;
+
+  va_start (ap, cmsgid);
+  fprintf (stderr, "nvptx-as: ");
+  vfprintf (stderr, cmsgid, ap);
+  fprintf (stderr, "\n");
+  va_end (ap);
+
+  unlink (outname);
+  exit (1);
+}
+
+struct Stmt;
+
+class symbol
+{
+ public:
+  symbol (const char *k) : key (k), stmts (0), pending (0), emitted (0)
+    { }
+
+  /* The name of the symbol.  */
+  const char *key;
+  /* A linked list of dependencies for the initializer.  */
+  std::list<symbol *> deps;
+  /* The statement in which it is defined.  */
+  struct Stmt *stmts;
+  bool pending;
+  bool emitted;
+};
+
+/* Hash and comparison functions for these hash tables.  */
+
+static int hash_string_eq (const void *, const void *);
+static hashval_t hash_string_hash (const void *);
+
+static int
+hash_string_eq (const void *s1_p, const void *s2_p)
+{
+  const char *const *s1 = (const char *const *) s1_p;
+  const char *s2 = (const char *) s2_p;
+  return strcmp (*s1, s2) == 0;
+}
+
+static hashval_t
+hash_string_hash (const void *s_p)
+{
+  const char *const *s = (const char *const *) s_p;
+  return (*htab_hash_string) (*s);
+}
+
+static htab_t symbol_table;
+
+/* Look up an entry in the symbol hash table.  */
+
+static symbol *
+symbol_hash_lookup (const char *string)
+{
+  void **e;
+  e = htab_find_slot_with_hash (symbol_table, string,
+                                (*htab_hash_string) (string),
+                                INSERT);
+  if (e == NULL)
+    return NULL;
+  if (*e == NULL)
+    *e = new symbol (string);
+
+  return (symbol *) *e;
+}
+
+#define COMMENT_PREFIX "#"
+
+typedef enum Kind
+{
+  /* 0-ff used for single char tokens */
+  K_symbol = 0x100, /* a symbol */
+  K_label,  /* a label defn (i.e. symbol:) */
+  K_ident,  /* other ident */
+  K_dotted, /* dotted identifier */
+  K_number,
+  K_string,
+  K_comment
+} Kind;
+
+typedef struct Token
+{
+  unsigned short kind : 12;
+  unsigned short space : 1; /* preceded by space */
+  unsigned short end : 1;   /* succeeded by end of line */
+  /* Length of token */
+  unsigned short len;
+
+  /* Token itself */
+  char const *ptr;
+} Token;
+
+/* statement info */
+typedef enum Vis
+{
+  V_dot = 0,  /* random pseudo */
+  V_var = 1,  /* var decl/defn */
+  V_func = 2, /* func decl/defn */
+  V_insn = 3, /* random insn */
+  V_label = 4, /* label defn */
+  V_comment = 5,
+  V_pred = 6,  /* predicate */
+  V_mask = 0x7,
+  V_global = 0x08, /* globalize */
+  V_weak = 0x10,   /* weakly globalize */
+  V_no_eol = 0x20, /* no end of line */
+  V_prefix_comment = 0x40 /* prefixed comment */
+} Vis;
+
+typedef struct Stmt
+{
+  struct Stmt *next;
+  Token *tokens;
+  symbol *sym;
+  unsigned char vis;
+  unsigned len : 12;
+} Stmt;
+
+struct id_map
+{
+  id_map *next;
+  char *ptx_name;
+};
+
+#define alloc_comment(S,E) alloc_stmt (V_comment, S, E, 0)
+#define append_stmt(V, S) ((S)->next = *(V), *(V) = (S))
+
+static Stmt *decls;
+static Stmt *fns;
+
+static id_map *func_ids, **funcs_tail = &func_ids;
+static id_map *var_ids, **vars_tail = &var_ids;
+
+static void
+record_id (const char *p1, id_map ***where)
+{
+  const char *end = strchr (p1, '\n');
+  if (!end)
+    fatal_error ("malformed ptx file");
+
+  id_map *v = XNEW (id_map);
+  size_t len = end - p1;
+  v->ptx_name = XNEWVEC (char, len + 1);
+  memcpy (v->ptx_name, p1, len);
+  v->ptx_name[len] = '\0';
+  v->next = NULL;
+  id_map **tail = *where;
+  *tail = v;
+  *where = &v->next;
+}
+
+/* Read the whole input file.  It will be NUL terminated (but
+   remember, there could be a NUL in the file itself.  */
+
+static const char *
+read_file (FILE *stream)
+{
+  size_t alloc = 16384;
+  size_t base = 0;
+  char *buffer;
+
+  if (!fseek (stream, 0, SEEK_END))
+    {
+      /* Get the file size.  */
+      long s = ftell (stream);
+      if (s >= 0)
+	alloc = s + 100;
+      fseek (stream, 0, SEEK_SET);
+    }
+  buffer = XNEWVEC (char, alloc);
+
+  for (;;)
+    {
+      size_t n = fread (buffer + base, 1, alloc - base - 1, stream);
+
+      if (!n)
+	break;
+      base += n;
+      if (base + 1 == alloc)
+	{
+	  alloc *= 2;
+	  buffer = XRESIZEVEC (char, buffer, alloc);
+	}
+    }
+  buffer[base] = 0;
+  return buffer;
+}
+
+/* Read a token, advancing ptr.
+   If we read a comment, append it to the comments block. */
+
+static Token *
+tokenize (const char *ptr)
+{
+  unsigned alloc = 1000;
+  unsigned num = 0;
+  Token *toks = XNEWVEC (Token, alloc);
+  int in_comment = 0;
+  int not_comment = 0;
+
+  for (;; num++)
+    {
+      const char *base;
+      unsigned kind;
+      int ws = 0;
+      int eol = 0;
+
+    again:
+      base = ptr;
+      if (in_comment)
+	goto block_comment;
+      switch (kind = *ptr++)
+	{
+	default:
+	  break;
+
+	case '\n':
+	  eol = 1;
+	  /* Fall through */
+	case ' ':
+	case '\t':
+	case '\r':
+	case '\v':
+	  /* White space */
+	  ws = not_comment;
+	  goto again;
+
+	case '/':
+	  {
+	    if (*ptr == '/')
+	      {
+		/* line comment.  Do not include trailing \n */
+		base += 2;
+		for (; *ptr; ptr++)
+		  if (*ptr == '\n')
+		    break;
+		kind = K_comment;
+	      }
+	    else if (*ptr == '*')
+	      {
+		/* block comment */
+		base += 2;
+		ptr++;
+
+	      block_comment:
+		eol = in_comment;
+		in_comment = 1;
+		for (; *ptr; ptr++)
+		  {
+		    if (*ptr == '\n')
+		      {
+			ptr++;
+			break;
+		      }
+		    if (ptr[0] == '*' && ptr[1] == '/')
+		      {
+			in_comment = 2;
+			ptr += 2;
+			break;
+		      }
+		  }
+		kind = K_comment;
+	      }
+	    else
+	      break;
+	  }
+	  break;
+
+	case '"':
+	  /* quoted string */
+	  kind = K_string;
+	  while (*ptr)
+	    if (*ptr == '"')
+	      {
+		ptr++;
+		break;
+	      }
+	    else if (*ptr++ == '\\')
+	      ptr++;
+	  break;
+
+	case '.':
+	  if (*ptr < '0' || *ptr > '9')
+	    {
+	      kind = K_dotted;
+	      ws = not_comment;
+	      goto ident;
+	    }
+	  /* FALLTHROUGH */
+	case '0'...'9':
+	  kind = K_number;
+	  goto ident;
+	  break;
+
+	case '$':  /* local labels.  */
+	case '%':  /* register names, pseudoes etc */
+	  kind = K_ident;
+	  goto ident;
+
+	case 'a'...'z':
+	case 'A'...'Z':
+	case '_':
+	  kind = K_symbol; /* possible symbol name */
+	ident:
+	  for (; *ptr; ptr++)
+	    {
+	      if (*ptr >= 'A' && *ptr <= 'Z')
+		continue;
+	      if (*ptr >= 'a' && *ptr <= 'z')
+		continue;
+	      if (*ptr >= '0' && *ptr <= '9')
+		continue;
+	      if (*ptr == '_' || *ptr == '$')
+		continue;
+	      if (*ptr == '.' && kind != K_dotted)
+		/* Idents starting with a dot, cannot have internal dots. */
+		continue;
+	      if ((*ptr == '+' || *ptr == '-')
+		  && kind == K_number
+		  && (ptr[-1] == 'e' || ptr[-1] == 'E'
+		      || ptr[-1] == 'p' || ptr[-1] == 'P'))
+		/* exponent */
+		continue;
+	      break;
+	    }
+	  if (*ptr == ':')
+	    {
+	      ptr++;
+	      kind = K_label;
+	    }
+	  break;
+	}
+
+      if (alloc == num)
+	{
+	  alloc *= 2;
+	  toks = XRESIZEVEC (Token, toks, alloc);
+	}
+      Token *tok = toks + num;
+
+      tok->kind = kind;
+      tok->space = ws;
+      tok->end = 0;
+      tok->ptr = base;
+      tok->len = ptr - base - in_comment;
+      in_comment &= 1;
+      not_comment = kind != K_comment;
+      if (eol && num)
+	tok[-1].end = 1;
+      if (!kind)
+	break;
+    }
+
+  return toks;
+}
+
+/* Write an encoded token. */
+
+static void
+write_token (FILE *out, Token const *tok)
+{
+  if (tok->space)
+    fputc (' ', out);
+
+  switch (tok->kind)
+    {
+    case K_string:
+      {
+	const char *c = tok->ptr + 1;
+	size_t len = tok->len - 2;
+
+	fputs ("\"", out);
+	while (len)
+	  {
+	    const char *bs = (const char *)memchr (c, '\\', len);
+	    size_t l = bs ? bs - c : len;
+
+	    fprintf (out, "%.*s", (int)l, c);
+	    len -= l;
+	    c += l;
+	    if (bs)
+	      {
+		fputs ("\\\\", out);
+		len--, c++;
+	      }
+	  }
+	fputs ("\"", out);
+      }
+      break;
+
+    default:
+      /* All other tokens shouldn't have anything magic in them */
+      fprintf (out, "%.*s", tok->len, tok->ptr);
+      break;
+    }
+
+  if (tok->end)
+    fputs ("\n", out);
+}
+
+static Stmt *
+alloc_stmt (unsigned vis, Token *tokens, Token *end, symbol *sym)
+{
+  static unsigned alloc = 0;
+  static Stmt *heap = 0;
+
+  if (!alloc)
+    {
+      alloc = 1000;
+      heap = XNEWVEC (Stmt, alloc);
+    }
+
+  Stmt *stmt = heap++;
+  alloc--;
+
+  tokens->space = 0;
+  stmt->next = 0;
+  stmt->vis = vis;
+  stmt->tokens = tokens;
+  stmt->len = end - tokens;
+  stmt->sym = sym;
+
+  return stmt;
+}
+
+static Stmt *
+rev_stmts (Stmt *stmt)
+{
+  Stmt *prev = 0;
+  Stmt *next;
+
+  while (stmt)
+    {
+      next = stmt->next;
+      stmt->next = prev;
+      prev = stmt;
+      stmt = next;
+    }
+
+  return prev;
+}
+
+static void
+write_stmt (FILE *out, const Stmt *stmt)
+{
+  for (int i = 0; i < stmt->len; i++)
+    {
+      if ((stmt->vis & V_mask) == V_comment)
+	fprintf (out, "//");
+      write_token (out, stmt->tokens + i);
+      if ((stmt->vis & V_mask) == V_pred)
+	fputc (' ', out);
+    }
+}
+
+static void
+write_stmts (FILE *out, const Stmt *stmts)
+{
+  for (; stmts; stmts = stmts->next)
+    write_stmt (out, stmts);
+}
+
+static Token *
+parse_insn (Token *tok)
+{
+  unsigned depth = 0;
+
+  do
+    {
+      Stmt *stmt;
+      unsigned s = V_insn;
+      Token *start = tok;
+
+      switch (tok++->kind)
+	{
+	case K_comment:
+	  while (tok->kind == K_comment)
+	    tok++;
+	  stmt = alloc_comment (start, tok);
+	  append_stmt (&fns, stmt);
+	  continue;
+
+	case '{':
+	  depth++;
+	  break;
+
+	case '}':
+	  depth--;
+	  break;
+
+	case K_label:
+	  tok[-1].end = 1;
+	  s = V_label;
+	  break;
+
+	case '@':
+	  tok->space = 0;
+	  if (tok->kind == '!')
+	    tok++;
+	  tok++;
+	  s = V_pred;
+	  break;
+
+	default:
+	  for (; tok->kind != ';'; tok++)
+	    {
+	      if (tok->kind == ',')
+		tok[1].space = 0;
+	    }
+	  tok++->end = 1;
+	  break;
+	}
+
+      stmt = alloc_stmt (s, start, tok, 0);
+      append_stmt (&fns, stmt);
+
+      if (!tok[-1].end && tok[0].kind == K_comment)
+	{
+	  stmt->vis |= V_no_eol;
+	  stmt = alloc_comment (tok, tok + 1);
+	  append_stmt (&fns, stmt);
+	  tok++;
+	}
+    }
+  while (depth);
+
+  return tok;
+}
+
+/* comma separated list of tokens */
+
+static Token *
+parse_list_nosemi (Token *tok)
+{
+  Token *start = tok;
+
+  do
+    if (!(++tok)->kind)
+      break;
+  while ((++tok)->kind == ',');
+
+  tok[-1].end = 1;
+  Stmt *stmt = alloc_stmt (V_dot, start, tok, 0);
+  append_stmt (&decls, stmt);
+
+  return tok;
+}
+
+#define is_keyword(T,S) \
+  (sizeof (S) == (T)->len && !memcmp ((T)->ptr + 1, (S), (T)->len - 1))
+
+static Token *
+parse_init (Token *tok, symbol *sym)
+{
+  for (;;)
+    {
+      Token *start = tok;
+      Token *def_tok = 0;
+      Stmt *stmt;
+
+      if (tok->kind == K_comment)
+	{
+	  while (tok->kind == K_comment)
+	    tok++;
+	  stmt = alloc_comment (start, tok);
+	  append_stmt (&sym->stmts, stmt);
+	  start = tok;
+	}
+
+      if (tok->kind == '{')
+	tok[1].space = 0;
+      /* Find the last symbol before the next comma.  This allows us
+	 to do the right thing for constructs like "generic (sym)".  */
+      for (; tok->kind != ',' && tok->kind != ';'; tok++)
+	if (tok->kind == K_symbol || tok->kind == K_ident)
+	  def_tok = tok;
+      if (def_tok)
+	sym->deps.push_back (symbol_hash_lookup (xstrndup (def_tok->ptr,
+							   def_tok->len)));
+      tok[1].space = 0;
+      int end = tok++->kind == ';';
+      stmt = alloc_stmt (V_insn, start, tok, 0);
+      append_stmt (&sym->stmts, stmt);
+      if (!tok[-1].end && tok->kind == K_comment)
+	{
+	  stmt->vis |= V_no_eol;
+	  stmt = alloc_comment (tok, tok + 1);
+	  append_stmt (&sym->stmts, stmt);
+	  tok++;
+	}
+      if (end)
+	break;
+    }
+  return tok;
+}
+
+static Token *
+parse_file (Token *tok)
+{
+  Stmt *comment = 0;
+
+  if (tok->kind == K_comment)
+    {
+      Token *start = tok;
+
+      while (tok->kind == K_comment)
+	{
+	  if (strncmp (tok->ptr, ":VAR_MAP ", 9) == 0)
+	    record_id (tok->ptr + 9, &vars_tail);
+	  if (strncmp (tok->ptr, ":FUNC_MAP ", 10) == 0)
+	    record_id (tok->ptr + 10, &funcs_tail);
+	  tok++;
+	}
+      comment = alloc_comment (start, tok);
+      comment->vis |= V_prefix_comment;
+    }
+
+  if (tok->kind == K_dotted)
+    {
+      if (is_keyword (tok, "version")
+	  || is_keyword (tok, "target")
+	  || is_keyword (tok, "address_size"))
+	{
+	  if (comment)
+	    append_stmt (&decls, comment);
+	  tok = parse_list_nosemi (tok);
+	}
+      else
+	{
+	  unsigned vis = 0;
+	  symbol *def = 0;
+	  unsigned is_decl = 0;
+	  Token *start, *def_token = 0;
+
+	  for (start = tok;
+	       tok->kind && tok->kind != '=' && tok->kind != K_comment
+		 && tok->kind != '{' && tok->kind != ';'; tok++)
+	    {
+	      if (is_keyword (tok, "global")
+		  || is_keyword (tok, "const"))
+		vis |= V_var;
+	      else if (is_keyword (tok, "func")
+		       || is_keyword (tok, "entry"))
+		vis |= V_func;
+	      else if (is_keyword (tok, "visible"))
+		vis |= V_global;
+	      else if (is_keyword (tok, "extern"))
+		is_decl = 1;
+	      else if (is_keyword (tok, "weak"))
+		vis |= V_weak;
+	      if (tok->kind == '(')
+		{
+		  tok[1].space = 0;
+		  tok[0].space = 1;
+		}
+	      else if (tok->kind == ')' && tok[1].kind != ';')
+		tok[1].space = 1;
+
+	      if (tok->kind == K_symbol || tok->kind == K_ident)
+		def_token = tok;
+	    }
+	  if (def_token)
+	    def = symbol_hash_lookup (xstrndup (def_token->ptr, def_token->len));
+
+	  if (!tok->kind)
+	    {
+	      /* end of file */
+	      if (comment)
+		append_stmt (&fns, comment);
+	    }
+	  else if (tok->kind == '{'
+		   || tok->kind == K_comment)
+	    {
+	      /* function defn */
+	      Stmt *stmt = alloc_stmt (vis, start, tok, def);
+	      if (comment)
+		{
+		  append_stmt (&fns, comment);
+		  stmt->vis |= V_prefix_comment;
+		}
+	      append_stmt (&fns, stmt);
+	      tok = parse_insn (tok);
+	    }
+	  else
+	    {
+	      int assign = tok->kind == '=';
+
+	      tok++->end = 1;
+	      if ((vis & V_mask) == V_var && !is_decl)
+		{
+		  /* variable */
+		  Stmt *stmt = alloc_stmt (vis, start, tok, def);
+		  if (comment)
+		    {
+		      append_stmt (&def->stmts, comment);
+		      stmt->vis |= V_prefix_comment;
+		    }
+		  append_stmt (&def->stmts, stmt);
+		  if (assign)
+		    tok = parse_init (tok, def);
+		}
+	      else
+		{
+		  /* declaration */
+		  Stmt *stmt = alloc_stmt (vis, start, tok, 0);
+		  if (comment)
+		    {
+		      append_stmt (&decls, comment);
+		      stmt->vis |= V_prefix_comment;
+		    }
+		  append_stmt (&decls, stmt);
+		}
+	    }
+	}
+    }
+  else
+    {
+      /* Something strange.  Ignore it.  */
+      if (comment)
+	append_stmt (&fns, comment);
+
+      while (tok->kind && !tok->end)
+	tok++;
+      if (tok->kind)
+	tok++;
+    }
+  return tok;
+}
+
+static void
+output_symbol (FILE *out, symbol *e)
+{
+  if (e->emitted)
+    return;
+  if (e->pending)
+    fatal_error ("circular reference in variable initializers");
+  e->pending = true;
+  std::list<symbol *>::iterator i;
+  for (i = e->deps.begin (); i != e->deps.end (); i++)
+    output_symbol (out, *i);
+  e->pending = false;
+  write_stmts (out, rev_stmts (e->stmts));
+  e->emitted = true;
+}
+
+static int
+traverse (void **slot, void *data)
+{
+  symbol *e = *(symbol **)slot;
+  output_symbol ((FILE *)data, e);
+  return 1;
+}
+
+static void
+process (FILE *in, FILE *out)
+{
+  symbol_table = htab_create (500, hash_string_hash, hash_string_eq,
+                              NULL);
+
+  const char *input = read_file (in);
+  Token *tok = tokenize (input);
+
+  do
+    tok = parse_file (tok);
+  while (tok->kind);
+
+  write_stmts (out, rev_stmts (decls));
+  htab_traverse (symbol_table, traverse, (void *)out);
+  write_stmts (out, rev_stmts (fns));
+}
+
+/* Wait for a process to finish, and exit if a nonzero status is found.  */
+
+int
+collect_wait (const char *prog, struct pex_obj *pex)
+{
+  int status;
+
+  if (!pex_get_status (pex, 1, &status))
+    fatal_error ("can't get program status: %m");
+  pex_free (pex);
+
+  if (status)
+    {
+      if (WIFSIGNALED (status))
+	{
+	  int sig = WTERMSIG (status);
+	  fatal_error ("%s terminated with signal %d [%s]%s",
+		       prog, sig, strsignal(sig),
+		       WCOREDUMP(status) ? ", core dumped" : "");
+	}
+
+      if (WIFEXITED (status))
+	return WEXITSTATUS (status);
+    }
+  return 0;
+}
+
+static void
+do_wait (const char *prog, struct pex_obj *pex)
+{
+  int ret = collect_wait (prog, pex);
+  if (ret != 0)
+    {
+      fatal_error ("%s returned %d exit status", prog, ret);
+    }
+}
+
+
+/* Execute a program, and wait for the reply.  */
+static void
+fork_execute (const char *prog, char *const *argv)
+{
+  struct pex_obj *pex = pex_init (0, "nvptx-as", NULL);
+  if (pex == NULL)
+    fatal_error ("pex_init failed: %m");
+
+  int err;
+  const char *errmsg;
+
+  errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, NULL,
+		    NULL, &err);
+  if (errmsg != NULL)
+    {
+      if (err != 0)
+	{
+	  errno = err;
+	  fatal_error ("%s: %m", errmsg);
+	}
+      else
+	fatal_error (errmsg);
+    }
+  do_wait (prog, pex);
+}
+
+static struct option long_options[] = {
+  {"traditional-format",     no_argument, 0,  0 },
+  {"save-temps",  no_argument,       0,  0 },
+  {"no-verify",  no_argument,       0,  0 },
+  {0,         0,                 0,  0 }
+};
+
+int
+main (int argc, char **argv)
+{
+  FILE *in = stdin;
+  FILE *out = stdout;
+  bool verbose __attribute__((unused)) = false;
+  bool verify = true;
+
+  int o;
+  int option_index = 0;
+  while ((o = getopt_long (argc, argv, "o:I:v", long_options, &option_index)) != -1)
+    {
+      switch (o)
+	{
+	case 0:
+	  if (option_index == 2)
+	    verify = false;
+	  break;
+	case 'v':
+	  verbose = true;
+	  break;
+	case 'o':
+	  if (outname != NULL)
+	    {
+	      fprintf (stderr, "multiple output files specified\n");
+	      exit (1);
+	    }
+	  outname = optarg;
+	  break;
+	case 'I':
+	  /* Ignore include paths.  */
+	  break;
+	default:
+	  break;
+	}
+    }
+
+  if (optind + 1 != argc)
+    fatal_error ("not exactly one input file specified");
+
+  out = fopen (outname, "w");
+  if (!out)
+    fatal_error ("cannot open '%s'", outname);
+
+  in = fopen (argv[optind], "r");
+  if (!in)
+    fatal_error ("cannot open input ptx file");
+
+  process (in, out);
+  fclose (out);
+
+  if (verify)
+    {
+      struct obstack argv_obstack;
+      obstack_init (&argv_obstack);
+      obstack_ptr_grow (&argv_obstack, "ptxas");
+      obstack_ptr_grow (&argv_obstack, "-c");
+      obstack_ptr_grow (&argv_obstack, "-o");
+      obstack_ptr_grow (&argv_obstack, "/dev/null");
+      obstack_ptr_grow (&argv_obstack, outname);
+      obstack_ptr_grow (&argv_obstack, "--gpu-name");
+      obstack_ptr_grow (&argv_obstack, "sm_30");
+      obstack_ptr_grow (&argv_obstack, NULL);
+      char *const *new_argv = XOBFINISH (&argv_obstack, char *const *);
+      fork_execute (new_argv[0], new_argv);
+    }
+  return 0;
+}
Index: git/gcc/config/nvptx/nvptx-ld.c
===================================================================
--- /dev/null
+++ git/gcc/config/nvptx/nvptx-ld.c
@@ -0,0 +1,498 @@
+/* An "linker" for ptx.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+   Contributed by Bernd Schmidt <bernds@codesourcery.com>
+
+   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 <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "hashtab.h"
+#include "obstack.h"
+#define HAVE_DECL_BASENAME 1
+#include "libiberty.h"
+
+#include <list>
+#include <string>
+#include <iostream>
+
+struct file_hash_entry;
+
+typedef struct symbol_hash_entry
+{
+  /* The name of the symbol.  */
+  const char *key;
+  /* A linked list of unresolved referenced symbols.  */
+  struct symbol_hash_entry **pprev, *next;
+  /* The file in which it is defined.  */
+  struct file_hash_entry *def;
+  int included;
+  int referenced;
+} symbol;
+
+typedef struct file_hash_entry
+{
+  struct file_hash_entry **pprev, *next;
+  const char *name;
+  const char *arname;
+  const char *data;
+  size_t len;
+} file;
+
+/* Hash and comparison functions for these hash tables.  */
+
+static int hash_string_eq (const void *, const void *);
+static hashval_t hash_string_hash (const void *);
+
+static int
+hash_string_eq (const void *s1_p, const void *s2_p)
+{
+  const char *const *s1 = (const char *const *) s1_p;
+  const char *s2 = (const char *) s2_p;
+  return strcmp (*s1, s2) == 0;
+}
+
+static hashval_t
+hash_string_hash (const void *s_p)
+{
+  const char *const *s = (const char *const *) s_p;
+  return (*htab_hash_string) (*s);
+}
+
+static htab_t symbol_table;
+
+/* Look up an entry in the symbol hash table.  */
+
+static struct symbol_hash_entry *
+symbol_hash_lookup (const char *string, int create)
+{
+  void **e;
+  e = htab_find_slot_with_hash (symbol_table, string,
+                                (*htab_hash_string) (string),
+                                create ? INSERT : NO_INSERT);
+  if (e == NULL)
+    return NULL;
+  if (*e == NULL)
+    {
+      struct symbol_hash_entry *v;
+      *e = v = XCNEW (struct symbol_hash_entry);
+      v->key = string;
+    }
+  return (struct symbol_hash_entry *) *e;
+}
+
+static struct file_hash_entry *
+file_hash_new (const char *data, size_t len, const char *arname, const char *name)
+{
+  struct file_hash_entry *v = XCNEW (struct file_hash_entry);
+  v->data = data;
+  v->len = len;
+  v->name = xstrdup (name);
+  v->arname = xstrdup (arname);
+  return v;
+}
+
+using namespace std;
+
+#define ARMAG  "!<arch>\012"    /* For COFF and a.out archives.  */
+#define SARMAG 8
+#define ARFMAG "`\012"
+
+struct ar_hdr
+{
+  char ar_name[16];             /* Name of this member.  */
+  char ar_date[12];             /* File mtime.  */
+  char ar_uid[6];               /* Owner uid; printed as decimal.  */
+  char ar_gid[6];               /* Owner gid; printed as decimal.  */
+  char ar_mode[8];              /* File mode, printed as octal.   */
+  char ar_size[10];             /* File size, printed as decimal.  */
+  char ar_fmag[2];              /* Should contain ARFMAG.  */
+};
+
+class archive
+{
+  FILE *f;
+  off_t flen;
+  off_t off;
+
+  char name[17];
+  char *contents;
+  size_t len;
+
+ public:
+  archive () : f (NULL), contents (NULL) { }
+  ~archive ()
+  {
+    discard_contents ();
+  }
+  void discard_contents ()
+  {
+    if (contents)
+      delete[] contents;
+    contents = NULL;
+  }
+  bool init (FILE *file)
+  {
+    char magic[SARMAG];
+    if (fread (magic, 1, SARMAG, file) != SARMAG)
+      return false;
+    if (memcmp (magic, ARMAG, SARMAG) != 0)
+      return false;
+    f = file;
+    fseek (f, 0, SEEK_END);
+    flen = ftell (f);
+    fseek (f, SARMAG, SEEK_SET);
+    off = SARMAG;
+
+    struct ar_hdr hdr;
+    if (fread (&hdr, sizeof hdr, 1, f) != 1)
+      return false;
+    if (hdr.ar_name[0] == '/' || hdr.ar_name[0] == ' ')
+      {
+	off += sizeof hdr;
+	long l = atol (hdr.ar_size);
+	if (l < 0 || off + l > flen)
+	  return false;
+	off += l;
+      }
+
+    fseek (f, off, SEEK_SET);
+    return true;
+  }
+
+  bool at_end ()
+  {
+    return off == flen;
+  }
+
+  bool next_file ()
+  {
+    discard_contents ();
+
+    struct ar_hdr hdr;
+    if (fread (&hdr, sizeof hdr, 1, f) != 1)
+      return false;
+    off += sizeof hdr;
+    long l = atol (hdr.ar_size);
+    if (l <= 0 || l > flen)
+      return false;
+    size_t read_len = l + (l & 1);
+    len = l;
+    contents = new char[read_len];
+    if (contents == NULL)
+      return false;
+    if (fread (contents, 1, read_len, f) != read_len)
+      return false;
+    off += read_len;
+    memcpy (name, hdr.ar_name, sizeof hdr.ar_name);
+    name[16] = '\0';
+    return true;
+  }
+  const char *get_contents () { return contents; }
+  const char *get_name () { return name; }
+  size_t get_len () { return len; }
+};
+
+FILE *
+path_open (const char *filename, list<string> &paths)
+{
+  FILE *f = fopen (filename, "r");
+  if (f)
+    return f;
+  if (strchr (filename, '/') != NULL)
+    return NULL;
+
+  for (list<string>::const_iterator iterator = paths.begin(), end = paths.end();
+       iterator != end;
+       ++iterator)
+    {
+      string tmp = *iterator;
+      tmp += '/';
+      tmp += filename;
+      FILE *f = fopen (tmp.c_str (), "r");
+      if (f)
+	return f;
+    }
+  return NULL;
+}
+
+static struct symbol_hash_entry *unresolved;
+
+static void
+enqueue_as_unresolved (struct symbol_hash_entry *e)
+{
+  e->pprev = &unresolved;
+  e->next = unresolved;
+  if (e->next)
+    e->next->pprev = &e->next;
+  unresolved = e;
+  e->referenced = true;
+}
+
+static void
+dequeue_unresolved (struct symbol_hash_entry *e)
+{
+  if (e->pprev != NULL)
+    {
+      if (e->next)
+	e->next->pprev = e->pprev;
+      *e->pprev = e->next;
+    }
+  e->pprev = NULL;
+}
+
+static void
+process_refs_defs (file *f, const char *ptx)
+{
+  while (*ptx != '\0')
+    {
+      if (strncmp (ptx, "\n// BEGIN GLOBAL ", 17) == 0)
+	{
+	  int type = 0;
+	  ptx += 17;
+	  if (strncmp (ptx, "VAR DEF: ", 9) == 0)
+	    {
+	      type = 1;
+	      ptx += 9;
+	    }
+	  else if (strncmp (ptx, "FUNCTION DEF: ", 14) == 0)
+	    {
+	      type = 1;
+	      ptx += 14;
+	    }
+	  if (strncmp (ptx, "VAR DECL: ", 10) == 0)
+	    {
+	      type = 2;
+	      ptx += 10;
+	    }
+	  else if (strncmp (ptx, "FUNCTION DECL: ", 15) == 0)
+	    {
+	      type = 2;
+	      ptx += 15;
+	    }
+	  if (type == 0)
+	    continue;
+	  const char *end = strchr (ptx, '\n');
+	  if (end == 0)
+	    end = ptx + strlen (ptx);
+	  if ((end - ptx == 6 && memcmp (ptx, "malloc", 6) == 0)
+	      || (end - ptx == 4 && memcmp (ptx, "free", 4) == 0)
+	      || (end - ptx == 7 && memcmp (ptx, "vprintf", 7) == 0))
+	    continue;
+	  const char *sym = xstrndup (ptx, end - ptx);
+	  struct symbol_hash_entry *e = symbol_hash_lookup (sym, 1);
+
+	  if (!e->included)
+	    {
+	      if (type == 1)
+		{
+		  if (f == NULL)
+		    {
+		      e->included = true;
+		      dequeue_unresolved (e);
+		    }
+		  else
+		    e->def = f;
+		}
+	      else
+		{
+		  if (f == NULL)
+		    {
+		      if (!e->referenced)
+			enqueue_as_unresolved (e);
+		    }
+		}
+	    }
+	}
+      ptx++;
+    }
+}
+
+int
+main (int argc, char **argv)
+{
+  const char *outname = NULL;
+  list<string> libraries;
+  list<string> libpaths;
+  bool verbose = false;
+
+  int o;
+  while ((o = getopt (argc, argv, "L:l:o:v")) != -1)
+    {
+      switch (o)
+	{
+	case 'v':
+	  verbose = true;
+	  break;
+	case 'o':
+	  if (outname != NULL)
+	    {
+	      cerr << "multiple output files specified\n";
+	      exit (1);
+	    }
+	  outname = optarg;
+	  break;
+	case 'l':
+	  libraries.push_back (optarg);
+	  break;
+	case 'L':
+	  libpaths.push_back (optarg);
+	  break;
+	default:
+	  break;
+	}
+    }
+
+  libraries.sort ();
+  libraries.unique ();
+  libpaths.unique ();
+
+  if (outname == NULL)
+    outname = "a.out";
+
+  symbol_table = htab_create (500, hash_string_hash, hash_string_eq,
+                              NULL);
+
+  FILE *outfile = fopen (outname, "w");
+  if (outfile == NULL)
+    {
+      cerr << "error opening output file\n";
+      exit (1);
+    }
+  list<string> inputfiles;
+  while (optind < argc)
+    inputfiles.push_back (argv[optind++]);
+
+  int idx = 0;
+  for (list<string>::const_iterator iterator = inputfiles.begin(), end = inputfiles.end();
+       iterator != end;
+       ++iterator)
+    {
+      const string &name = *iterator;
+      FILE *f = path_open (name.c_str (), libpaths);
+      if (f == NULL)
+	{
+	  cerr << "error opening " << name << "\n";
+	  goto error_out;
+	}
+      fseek (f, 0, SEEK_END);
+      off_t len = ftell (f);
+      fseek (f, 0, SEEK_SET);
+      char *buf = new char[len + 1];
+      fread (buf, 1, len, f);
+      buf[len] = '\0';
+      if (ferror (f))
+	{
+	  cerr << "error reading " << name << "\n";
+	  goto error_out;
+	}
+      size_t out = fwrite (buf, 1, len, outfile);
+      if (out != len)
+	{
+	  cerr << "error writing to output file\n";
+	  goto error_out;
+	}
+      process_refs_defs (NULL, buf);
+      free (buf);
+      if (verbose)
+	cout << "Linking " << name << " as " << idx++ << "\n";
+      fputc ('\0', outfile);
+    }
+  for (list<string>::const_iterator iterator = libraries.begin(), end = libraries.end();
+       iterator != end;
+       ++iterator)
+    {
+      const string &name = "lib" + *iterator + ".a";
+      if (verbose)
+	cout << "trying lib " << name << "\n";
+      FILE *f = path_open (name.c_str (), libpaths);
+      if (f == NULL)
+	{
+	  cerr << "error opening " << name << "\n";
+	  goto error_out;
+	}
+      archive ar;
+      if (!ar.init (f))
+	{
+	  cerr << name << " is not a valid archive\n";
+	  goto error_out;
+	}
+      while (!ar.at_end ())
+	{
+	  if (!ar.next_file ())
+	    {
+	      cerr << "error reading from archive " << name << "\n";
+	      goto error_out;
+	    }
+	  const char *p = xstrdup (ar.get_contents ());
+	  size_t len = ar.get_len ();
+	  file *f = file_hash_new (p, len, name.c_str (), ar.get_name ());
+	  process_refs_defs (f, p);
+	}
+    }
+
+  while (unresolved)
+    {
+      struct file_hash_entry *to_add = NULL;
+      struct symbol_hash_entry *e;
+      for (e = unresolved; e; e = e->next)
+	{
+	  struct file_hash_entry *f = e->def;
+	  if (!f)
+	    {
+	      cerr << "unresolved symbol " << e->key << "\n";
+	      goto error_out;
+	    }
+	  if (verbose)
+	    cout << "Resolving " << e->key << "\n";
+	  if (!f->pprev)
+	    {
+	      f->pprev = &to_add;
+	      f->next = to_add;
+	      to_add = f;
+	    }
+	  e->included = true;
+	  e->pprev = NULL;
+	}
+      unresolved = NULL;
+      assert (to_add != NULL);
+      struct file_hash_entry *f;
+      for (f = to_add; f; f = f->next)
+	{
+	  f->pprev = NULL;
+	  if (verbose)
+	    cout << "Linking " << f->arname << "::" << f->name << " as " << idx++ << "\n";
+	  if (fwrite (f->data, 1, f->len, outfile) != f->len)
+	    {
+	      cerr << "error writing to output file\n";
+	      goto error_out;
+	    }
+	  fputc ('\0', outfile);
+	  process_refs_defs (NULL, f->data);
+	}
+    }
+  return 0;
+
+ error_out:
+  fclose (outfile);
+  unlink (outname);
+  return 1;
+}
Index: git/gcc/config/nvptx/t-nvptx
===================================================================
--- git.orig/gcc/config/nvptx/t-nvptx
+++ git/gcc/config/nvptx/t-nvptx
@@ -1,2 +1,27 @@
 #
 
+nvptx-ld.o: $(srcdir)/config/nvptx/nvptx-ld.c
+	$(COMPILE) $<
+	$(POSTCOMPILE)
+
+collect-ld$(exeext): nvptx-ld.o $(LIBIBERTY)
+	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+	  nvptx-ld.o $(LIBIBERTY)
+
+nvptx-as.o: $(srcdir)/config/nvptx/nvptx-as.c
+	$(COMPILE) $<
+	$(POSTCOMPILE)
+
+as$(exeext): nvptx-as.o $(LIBIBERTY)
+	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+	  nvptx-as.o $(LIBIBERTY)
+
+ar$(exeext):
+	echo -e "#! /bin/sh\n$(AR) \"$$""@\"" >$@
+	chmod a+x $@
+
+ranlib$(exeext):
+	echo -e "#! /bin/sh\n$(RANLIB) \"$$""@\"" >$@
+	chmod a+x $@
+
+
Index: git/configure
===================================================================
--- git.orig/configure
+++ git/configure
@@ -13607,7 +13607,95 @@ fi
 
 RAW_CXX_FOR_TARGET="$CXX_FOR_TARGET"
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target ar" >&5
+case "${target}" in
+  nvptx-*)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target ar" >&5
+$as_echo_n "checking where to find the target ar... " >&6; }
+if test "x${build}" != "x${host}" ; then
+  if expr "x$AR_FOR_TARGET" : "x/" > /dev/null; then
+    # We already found the complete path
+    ac_dir=`dirname $AR_FOR_TARGET`
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+  else
+    # Canadian cross, just use what we found
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+  fi
+else
+  ok=yes
+  case " ${configdirs} " in
+    *" gcc "*) ;;
+    *) ok=no ;;
+  esac
+
+  if test $ok = yes; then
+    # An in-tree tool is available and we can use it
+    AR_FOR_TARGET='$$r/$(HOST_SUBDIR)/gcc/ar'
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: just compiled" >&5
+$as_echo "just compiled" >&6; }
+  elif expr "x$AR_FOR_TARGET" : "x/" > /dev/null; then
+    # We already found the complete path
+    ac_dir=`dirname $AR_FOR_TARGET`
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+  elif test "x$target" = "x$host"; then
+    # We can use an host tool
+    AR_FOR_TARGET='$(AR)'
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: host tool" >&5
+$as_echo "host tool" >&6; }
+  else
+    # We need a cross tool
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+  fi
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target ranlib" >&5
+$as_echo_n "checking where to find the target ranlib... " >&6; }
+if test "x${build}" != "x${host}" ; then
+  if expr "x$RANLIB_FOR_TARGET" : "x/" > /dev/null; then
+    # We already found the complete path
+    ac_dir=`dirname $RANLIB_FOR_TARGET`
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+  else
+    # Canadian cross, just use what we found
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+  fi
+else
+  ok=yes
+  case " ${configdirs} " in
+    *" gcc "*) ;;
+    *) ok=no ;;
+  esac
+
+  if test $ok = yes; then
+    # An in-tree tool is available and we can use it
+    RANLIB_FOR_TARGET='$$r/$(HOST_SUBDIR)/gcc/ranlib'
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: just compiled" >&5
+$as_echo "just compiled" >&6; }
+  elif expr "x$RANLIB_FOR_TARGET" : "x/" > /dev/null; then
+    # We already found the complete path
+    ac_dir=`dirname $RANLIB_FOR_TARGET`
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+  elif test "x$target" = "x$host"; then
+    # We can use an host tool
+    RANLIB_FOR_TARGET='$(RANLIB)'
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: host tool" >&5
+$as_echo "host tool" >&6; }
+  else
+    # We need a cross tool
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+  fi
+fi
+
+    ;;
+  *)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target ar" >&5
 $as_echo_n "checking where to find the target ar... " >&6; }
 if test "x${build}" != "x${host}" ; then
   if expr "x$AR_FOR_TARGET" : "x/" > /dev/null; then
@@ -13649,6 +13737,50 @@ $as_echo "pre-installed" >&6; }
   fi
 fi
 
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target ranlib" >&5
+$as_echo_n "checking where to find the target ranlib... " >&6; }
+if test "x${build}" != "x${host}" ; then
+  if expr "x$RANLIB_FOR_TARGET" : "x/" > /dev/null; then
+    # We already found the complete path
+    ac_dir=`dirname $RANLIB_FOR_TARGET`
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+  else
+    # Canadian cross, just use what we found
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+  fi
+else
+  ok=yes
+  case " ${configdirs} " in
+    *" binutils "*) ;;
+    *) ok=no ;;
+  esac
+
+  if test $ok = yes; then
+    # An in-tree tool is available and we can use it
+    RANLIB_FOR_TARGET='$$r/$(HOST_SUBDIR)/binutils/ranlib'
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: just compiled" >&5
+$as_echo "just compiled" >&6; }
+  elif expr "x$RANLIB_FOR_TARGET" : "x/" > /dev/null; then
+    # We already found the complete path
+    ac_dir=`dirname $RANLIB_FOR_TARGET`
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
+$as_echo "pre-installed in $ac_dir" >&6; }
+  elif test "x$target" = "x$host"; then
+    # We can use an host tool
+    RANLIB_FOR_TARGET='$(RANLIB)'
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: host tool" >&5
+$as_echo "host tool" >&6; }
+  else
+    # We need a cross tool
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
+$as_echo "pre-installed" >&6; }
+  fi
+fi
+
+    ;;
+esac
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target as" >&5
 $as_echo_n "checking where to find the target as... " >&6; }
 if test "x${build}" != "x${host}" ; then
@@ -14193,48 +14325,6 @@ $as_echo "pre-installed in $ac_dir" >&6;
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: host tool" >&5
 $as_echo "host tool" >&6; }
   else
-    # We need a cross tool
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
-$as_echo "pre-installed" >&6; }
-  fi
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target ranlib" >&5
-$as_echo_n "checking where to find the target ranlib... " >&6; }
-if test "x${build}" != "x${host}" ; then
-  if expr "x$RANLIB_FOR_TARGET" : "x/" > /dev/null; then
-    # We already found the complete path
-    ac_dir=`dirname $RANLIB_FOR_TARGET`
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
-$as_echo "pre-installed in $ac_dir" >&6; }
-  else
-    # Canadian cross, just use what we found
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
-$as_echo "pre-installed" >&6; }
-  fi
-else
-  ok=yes
-  case " ${configdirs} " in
-    *" binutils "*) ;;
-    *) ok=no ;;
-  esac
-
-  if test $ok = yes; then
-    # An in-tree tool is available and we can use it
-    RANLIB_FOR_TARGET='$$r/$(HOST_SUBDIR)/binutils/ranlib'
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: just compiled" >&5
-$as_echo "just compiled" >&6; }
-  elif expr "x$RANLIB_FOR_TARGET" : "x/" > /dev/null; then
-    # We already found the complete path
-    ac_dir=`dirname $RANLIB_FOR_TARGET`
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed in $ac_dir" >&5
-$as_echo "pre-installed in $ac_dir" >&6; }
-  elif test "x$target" = "x$host"; then
-    # We can use an host tool
-    RANLIB_FOR_TARGET='$(RANLIB)'
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: host tool" >&5
-$as_echo "host tool" >&6; }
-  else
     # We need a cross tool
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: pre-installed" >&5
 $as_echo "pre-installed" >&6; }
Index: git/configure.ac
===================================================================
--- git.orig/configure.ac
+++ git/configure.ac
@@ -3271,7 +3271,16 @@ ACX_CHECK_INSTALLED_TARGET_TOOL(WINDMC_F
 
 RAW_CXX_FOR_TARGET="$CXX_FOR_TARGET"
 
-GCC_TARGET_TOOL(ar, AR_FOR_TARGET, AR, [binutils/ar])
+case "${target}" in
+  nvptx-*)
+    GCC_TARGET_TOOL(ar, AR_FOR_TARGET, AR, [gcc/ar])
+    GCC_TARGET_TOOL(ranlib, RANLIB_FOR_TARGET, RANLIB, [gcc/ranlib])
+    ;;
+  *)
+    GCC_TARGET_TOOL(ar, AR_FOR_TARGET, AR, [binutils/ar])
+    GCC_TARGET_TOOL(ranlib, RANLIB_FOR_TARGET, RANLIB, [binutils/ranlib])
+    ;;
+esac
 GCC_TARGET_TOOL(as, AS_FOR_TARGET, AS, [gas/as-new])
 GCC_TARGET_TOOL(cc, CC_FOR_TARGET, CC, [gcc/xgcc -B$$r/$(HOST_SUBDIR)/gcc/])
 dnl see comments for CXX_FOR_TARGET_FLAG_TO_PASS
@@ -3293,7 +3302,6 @@ GCC_TARGET_TOOL(ld, LD_FOR_TARGET, LD, [
 GCC_TARGET_TOOL(lipo, LIPO_FOR_TARGET, LIPO)
 GCC_TARGET_TOOL(nm, NM_FOR_TARGET, NM, [binutils/nm-new])
 GCC_TARGET_TOOL(objdump, OBJDUMP_FOR_TARGET, OBJDUMP, [binutils/objdump])
-GCC_TARGET_TOOL(ranlib, RANLIB_FOR_TARGET, RANLIB, [binutils/ranlib])
 GCC_TARGET_TOOL(readelf, READELF_FOR_TARGET, READELF, [binutils/readelf])
 GCC_TARGET_TOOL(strip, STRIP_FOR_TARGET, STRIP, [binutils/strip-new])
 GCC_TARGET_TOOL(windres, WINDRES_FOR_TARGET, WINDRES, [binutils/windres])
