diff -Nuar binutils-2.11.93.0.2.orig/gas/as.c binutils-2.11.93.0.2/gas/as.c
--- binutils-2.11.93.0.2.orig/gas/as.c	Sun Feb  3 22:22:31 2002
+++ binutils-2.11.93.0.2/gas/as.c	Fri Dec 27 17:26:24 2002
@@ -808,6 +808,10 @@
   myname = argv[0];
   xmalloc_set_program_name (myname);
 
+#ifdef CHECK_ENVIRONMENT
+  CHECK_ENVIRONMENT
+#endif
+  
   START_PROGRESS (myname, 0);
 
 #ifndef OBJ_DEFAULT_OUTPUT_FILE_NAME
diff -Nuar binutils-2.11.93.0.2.orig/gas/config/tc-arm.c binutils-2.11.93.0.2/gas/config/tc-arm.c
--- binutils-2.11.93.0.2.orig/gas/config/tc-arm.c	Sun Feb  3 22:22:31 2002
+++ binutils-2.11.93.0.2/gas/config/tc-arm.c	Fri Dec 27 17:26:24 2002
@@ -9209,6 +9209,9 @@
 	mfpu_opt = march_fpu_opt;
     }
 
+  if (mcpu_cpu_opt == -1)
+    set_default_cpu();
+
   if (mfpu_opt == -1)
     {
       if (mcpu_cpu_opt == -1)
@@ -10483,6 +10486,65 @@
   as_bad (_("bad instruction `%s'"), start);
 }
 
+static int find_family_cpu
+  PARAMS ((char ** ptr));
+
+static int
+find_family_cpu (family_cpu)
+	char **family_cpu;
+{
+  char *p;
+  int len;
+
+  p = getenv("CROSS_COMPILE");
+  if (p && *p)
+    {
+      p = basename(p);
+      len = strlen(p);
+      *family_cpu = (char *) xmalloc(len + 1);
+      strcpy(*family_cpu, p);
+      if ((*family_cpu)[len - 1] == '-')
+        (*family_cpu)[len - 1] = '\0';
+      return 1;
+    }
+  return 0;
+}
+				
+/* set_default_cpu
+      If the CROSS_COMPILE environment variable is set
+      set cpu-dependent flags. They will be overridden by command-line
+      flags */
+void
+set_default_cpu ()
+{
+  char * family_cpu;
+  int    i;
+  char * cpu;
+
+  struct target_cpu {
+    char *	target_arch;
+    int		cpu;
+  } target_cpu_tbl[] = {
+    {"920TDI", ARM_ARCH_V4T}
+  };
+
+  if (! find_family_cpu(&family_cpu))
+    as_fatal (_("The CROSS_COMPILE environment variable is not set"));
+
+  if (!strncasecmp(family_cpu, "arm_", 4))
+    {
+      cpu = family_cpu + 4;
+      for (i = 0; i < sizeof(target_cpu_tbl)/sizeof(target_cpu_tbl[0]); i++)
+        {
+          if (!strcmp(target_cpu_tbl[i].target_arch, cpu))
+            {
+              mcpu_cpu_opt = target_cpu_tbl[i].cpu;
+              break;
+            }
+        }
+    }
+}
+
 /* md_parse_option
       Invocation line includes a switch not recognized by the base assembler.
       See if it's a processor-specific option.  
diff -Nuar binutils-2.11.93.0.2.orig/gas/config/tc-mips.c binutils-2.11.93.0.2/gas/config/tc-mips.c
--- binutils-2.11.93.0.2.orig/gas/config/tc-mips.c	Sun Feb  3 22:22:31 2002
+++ binutils-2.11.93.0.2/gas/config/tc-mips.c	Fri Dec 27 17:27:11 2002
@@ -9738,6 +9738,65 @@
 };
 size_t md_longopts_size = sizeof (md_longopts);
 
+static int find_family_cpu
+  PARAMS ((char ** ptr));
+
+/* set_default_cpu
+      If the CROSS_COMPILE environment variable is set
+      set cpu-dependent flags. They will be overridden by command-line
+      flags */
+void
+set_default_cpu ()
+{
+  char * family_cpu;
+  int    i;
+  char * cpu;
+
+  struct target_cpu {
+    char * target_arch;
+    int    cpu;
+  } target_cpu_tbl[] = {
+    {"4KC",   CPU_MIPS32 }
+  };
+
+  if (! find_family_cpu(&family_cpu))
+    as_fatal (_("The CROSS_COMPILE environment variable is not set"));
+
+  if (!strncasecmp(family_cpu, "mips_", 5))
+    {
+      cpu = family_cpu + 5;
+      for (i = 0; i < sizeof(target_cpu_tbl)/sizeof(target_cpu_tbl[0]); i++)
+        {
+          if (!strcmp(target_cpu_tbl[i].target_arch, cpu))
+            {
+              mips_cpu = target_cpu_tbl[i].cpu; mips_arch=mips_cpu;
+              break;
+            }
+        }
+    }
+}
+
+static int
+find_family_cpu (family_cpu)
+      char **family_cpu;
+{
+  char *p;
+  int len;
+
+  p = getenv("CROSS_COMPILE");
+  if (p && *p)
+    {
+      p = basename(p);
+      len = strlen(p);
+      *family_cpu = (char *) xmalloc(len + 1);
+      strcpy(*family_cpu, p);
+      if ((*family_cpu)[len - 1] == '-')
+        (*family_cpu)[len - 1] = '\0';
+      return 1;
+    }
+  return 0;
+}
+
 int
 md_parse_option (c, arg)
      int c;
@@ -13168,6 +13227,7 @@
   { "mipsisa32",      0,      ISA_MIPS32,     CPU_MIPS32, },
   { "Generic-MIPS32", 0,      ISA_MIPS32,     CPU_MIPS32, },
   { "4kc",            0,      ISA_MIPS32,     CPU_MIPS32, },
+  { "r4kc",           0,      ISA_MIPS32,     CPU_MIPS32, },
   { "4km",            0,      ISA_MIPS32,     CPU_MIPS32, },
   { "4kp",            0,      ISA_MIPS32,     CPU_MIPS32, },
 
diff -Nuar binutils-2.11.93.0.2.orig/gas/config/tc-mips.h binutils-2.11.93.0.2/gas/config/tc-mips.h
--- binutils-2.11.93.0.2.orig/gas/config/tc-mips.h	Sun Feb  3 22:22:31 2002
+++ binutils-2.11.93.0.2/gas/config/tc-mips.h	Fri Dec 27 17:26:24 2002
@@ -149,4 +149,7 @@
 extern void mips_enable_auto_align PARAMS ((void));
 #define md_elf_section_change_hook()	mips_enable_auto_align()
 
+#define CHECK_ENVIRONMENT set_default_cpu();
+  extern void set_default_cpu PARAMS (( ));
+
 #endif /* TC_MIPS */
diff -Nuar binutils-2.11.93.0.2.orig/gas/config/tc-ppc.c binutils-2.11.93.0.2/gas/config/tc-ppc.c
--- binutils-2.11.93.0.2.orig/gas/config/tc-ppc.c	Sun Feb  3 22:22:31 2002
+++ binutils-2.11.93.0.2/gas/config/tc-ppc.c	Fri Dec 27 17:26:24 2002
@@ -805,6 +805,70 @@
 };
 const size_t md_longopts_size = sizeof (md_longopts);
 
+static int find_family_cpu
+  PARAMS ((char ** ptr));
+
+/* set_default_cpu
+      If the CROSS_COMPILE environment variable is set
+      set cpu-dependent flags. They will be overridden by command-line
+      flags */
+void
+set_default_cpu ()
+{
+  char * family_cpu;
+  int    i;
+  char * cpu;
+
+  struct target_cpu {
+    char * target_arch;
+    int    flags;
+  } target_cpu_tbl[] = {
+    {"4xx",   PPC_OPCODE_PPC },
+    {"4xxFP", PPC_OPCODE_PPC },
+    {"74xx",  PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC},
+    {"7xx",   PPC_OPCODE_PPC },
+    {"82xx",  PPC_OPCODE_PPC },
+    {"8xx",   PPC_OPCODE_PPC }
+  };
+
+  if (! find_family_cpu(&family_cpu))
+    as_fatal (_("The CROSS_COMPILE environment variable is not set"));
+
+  if (!strncasecmp(family_cpu, "ppc_", 4))
+    {
+      cpu = family_cpu + 4;
+      for (i = 0; i < sizeof(target_cpu_tbl)/sizeof(target_cpu_tbl[0]); i++)
+        {
+          if (!strcmp(target_cpu_tbl[i].target_arch, cpu))
+            {
+              ppc_cpu = target_cpu_tbl[i].flags;
+              break;
+            }
+        }
+    }
+}
+
+static int
+find_family_cpu (family_cpu)
+      char **family_cpu;
+{
+  char *p;
+  int len;
+
+  p = getenv("CROSS_COMPILE");
+  if (p && *p)
+    {
+      p = basename(p);
+      len = strlen(p);
+      *family_cpu = (char *) xmalloc(len + 1);
+      strcpy(*family_cpu, p);
+      if ((*family_cpu)[len - 1] == '-')
+        (*family_cpu)[len - 1] = '\0';
+      return 1;
+    }
+  return 0;
+}
+
 int
 md_parse_option (c, arg)
      int c;
diff -Nuar binutils-2.11.93.0.2.orig/gas/config/tc-ppc.h binutils-2.11.93.0.2/gas/config/tc-ppc.h
--- binutils-2.11.93.0.2.orig/gas/config/tc-ppc.h	Sat Nov 17 01:05:52 2001
+++ binutils-2.11.93.0.2/gas/config/tc-ppc.h	Fri Dec 27 17:26:24 2002
@@ -297,3 +297,7 @@
 extern int ppc_parse_name PARAMS ((const char *, struct expressionS *));
 
 #define md_operand(x)
+
+#define CHECK_ENVIRONMENT set_default_cpu();
+  extern void set_default_cpu PARAMS (( ));
+
diff -Nuar binutils-2.11.93.0.2.orig/ld/Makefile.in binutils-2.11.93.0.2/ld/Makefile.in
--- binutils-2.11.93.0.2.orig/ld/Makefile.in	Fri Dec 27 17:25:45 2002
+++ binutils-2.11.93.0.2/ld/Makefile.in	Fri Dec 27 17:26:24 2002
@@ -1775,8 +1775,7 @@
 	n=`echo ld | sed '$(transform)'`; \
 	if [ "$(bindir)/$$n$(EXEEXT)" != "$(tooldir)/bin/ld$(EXEEXT)" ]; then \
 	  rm -f $(tooldir)/bin/ld$(EXEEXT); \
-	  ln $(bindir)/$$n$(EXEEXT) $(tooldir)/bin/ld$(EXEEXT) >/dev/null 2>/dev/null \
-	  || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(tooldir)/bin/ld$(EXEEXT); \
+	  ln -s ../../bin/$$n$(EXEEXT) $(tooldir)/bin/ld$(EXEEXT) >/dev/null 2>/dev/null; \
 	fi
 
 install-data-local:
diff -Nuar binutils-2.11.93.0.2.orig/ld/ldfile.c binutils-2.11.93.0.2/ld/ldfile.c
--- binutils-2.11.93.0.2.orig/ld/ldfile.c	Sat Nov 17 01:05:53 2001
+++ binutils-2.11.93.0.2/ld/ldfile.c	Fri Dec 27 17:26:24 2002
@@ -36,6 +36,9 @@
 #include "ldemul.h"
 #include "libiberty.h"
 
+extern char *cross_dir;
+extern char *replace(char *, char *);
+
 const char *ldfile_input_filename;
 boolean ldfile_assumed_script = false;
 const char *ldfile_output_machine_name = "";
@@ -90,6 +93,9 @@
   new = (search_dirs_type *) xmalloc (sizeof (search_dirs_type));
   new->name = name;
   new->cmdline = cmdline;
+  if (cross_dir && !cmdline)
+    new->name = replace(cross_dir, name);
+
   if (append)
     {
       new->next = NULL;
diff -Nuar binutils-2.11.93.0.2.orig/ld/ldmain.c binutils-2.11.93.0.2/ld/ldmain.c
--- binutils-2.11.93.0.2.orig/ld/ldmain.c	Fri Dec 27 17:25:45 2002
+++ binutils-2.11.93.0.2/ld/ldmain.c	Fri Dec 27 17:26:24 2002
@@ -47,6 +47,7 @@
 #endif
 
 #include <string.h>
+#include <sys/param.h>
 
 #ifdef HAVE_SBRK
 #ifdef NEED_DECLARATION_SBRK
@@ -54,6 +55,14 @@
 #endif
 #endif
 
+char *cross_dir;
+static char *family_cpu;
+static void find_cross_dir(char *, char **);
+static void remove_relative_paths (char *);
+static int find_family_cpu(char **);
+static void set_target_dir();
+char *replace (char *, char *);
+
 static char *get_emulation PARAMS ((int, char **));
 static void set_scripts_dir PARAMS ((void));
 
@@ -178,6 +187,10 @@
   program_name = argv[0];
   xmalloc_set_program_name (program_name);
 
+  if (!find_family_cpu(&family_cpu)) {
+    einfo (_("%P%F: the CROSS_COMPILE environment variable is not set\n"));
+  }
+  
   START_PROGRESS (program_name, 0);
 
   bfd_init ();
@@ -219,6 +232,8 @@
   command_line.check_section_addresses = true;
   command_line.multilib_dir = NULL;
 
+  find_cross_dir(program_name, &cross_dir);
+
   /* We initialize DEMANGLING based on the environment variable
      COLLECT_NO_DEMANGLE.  The gcc collect2 program will demangle the
      output of the linker, unless COLLECT_NO_DEMANGLE is set in the
@@ -311,6 +326,10 @@
      the -L's in argv have been processed.  */
   set_scripts_dir ();
 
+  /* Add target-specific directories */
+  set_target_dir ();
+
+  
   /* If we have not already opened and parsed a linker script
      read the emulation's appropriate default script.  */
   if (saved_script_handle == NULL)
@@ -620,7 +639,12 @@
   struct stat s;
   boolean res;
 
+  if (cross_dir)
+  {
+    dir = replace(cross_dir, dir);
+  }
   dirlen = strlen (dir);
+
   /* sizeof counts the terminating NUL.  */
   buf = (char *) xmalloc (dirlen + sizeof ("/ldscripts"));
   sprintf (buf, "%s/ldscripts", dir);
@@ -1427,3 +1451,254 @@
 
   return true;
 }
+
+#ifndef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#endif
+
+#ifndef PATH_SEPARATOR
+#define PATH_SEPARATOR ':'
+#endif
+
+/* Remove relative paths -- .. and . */
+static void
+remove_relative_paths (char * path)
+{
+  char *p, *s;
+
+  p = path;
+  while ((p = strchr (p, DIR_SEPARATOR)))
+  {
+    p++;
+    if (*p == '.')
+    {
+      p++;
+      if (*p == DIR_SEPARATOR)
+      {
+        /*  Translate "/./" ==> "/"  */
+        strcpy (p-2, p);
+      }
+      else if (*p == '.' && *(p+1) == DIR_SEPARATOR)
+      {
+        /*  Translate "/<whatever>/../" ==> "/"  */
+        s = p + 1;
+        p -= 3;
+        while ( p > path && *p != DIR_SEPARATOR)
+          p--;
+        strcpy (p, s);
+      }
+    }
+  }
+}
+
+/* Find cross directory root */
+static void
+find_cross_dir(char *progname, char **ptr)
+{
+  char *fullpath = xmalloc(MAXPATHLEN);
+  char *linkfile = xmalloc(MAXPATHLEN);
+  char *realpath = xmalloc(MAXPATHLEN);
+  struct stat file;
+  int ret = 0;
+  char *p;
+  int i;
+
+  *ptr = 0;
+
+  if (strchr (progname, '/'))
+  {
+    if (progname[0] == '/')
+    {
+      /* We have absolute path */
+      strcpy (fullpath, progname);
+    } else {
+      /* We have relative path, prepend $cwd */
+      getcwd (fullpath, MAXPATHLEN);
+      strcat (fullpath, "/");
+      strcat (fullpath, progname);
+    }
+  } else {
+    /* Search pathlist for matching progname  */
+    char *path;
+    char *beg, *end;
+
+    path = getenv("PATH");
+    beg = path;
+    while (1)
+    {
+      for (end = beg; *end && *end != PATH_SEPARATOR; end++) ;
+      strncpy (fullpath, beg, end - beg);
+      fullpath[end - beg] = '\0';
+      if (fullpath[end - beg - 1] == DIR_SEPARATOR)
+        fullpath[end - beg - 1] = '\0';
+      if (strcmp (fullpath, ".") == 0)
+        getcwd (fullpath, MAXPATHLEN);
+      strcat (fullpath, "/");
+      strcat (fullpath, progname);
+      if ((lstat (fullpath, &file) == 0) &&
+        (S_ISREG(file.st_mode) || S_ISLNK(file.st_mode))) break;
+      if (*end == '\0') {
+        free(realpath);
+        goto RET; /* Not found on path */
+      }
+      beg = end + 1;
+    }
+  }
+
+  /* Resolve all symbolic links in the full path */
+  while (fullpath[0])
+  {
+    char *t, *s, *q;
+    int len, off;
+
+    while ((ret = lstat (fullpath, &file)) == 0 && S_ISLNK(file.st_mode))
+    {
+      /* fullpath is a link */
+            linkfile[readlink (fullpath, linkfile, MAXPATHLEN)] = '\0';
+      if (linkfile[0] == DIR_SEPARATOR)
+      {
+        /* Link replaces path */
+        strcpy (fullpath, linkfile);
+      }
+      else
+      {
+        /* Link is relative to current directory */
+        q = strrchr (fullpath, DIR_SEPARATOR);
+        *(q + 1) = '\0';
+        strcat (fullpath, linkfile);
+      }
+      /* We might have added more relative paths -- remove them */
+      remove_relative_paths (fullpath);
+    }
+    if (ret)
+    {
+      free(realpath);
+      goto RET;
+    }
+    /* Strip off the last segment of the path */
+    if ((q = strrchr (fullpath, DIR_SEPARATOR)))
+      *q++ = '\0';
+    else
+      q = fullpath;
+
+    /* Shift realpath right to make room for new segment and slash */
+    off = strlen (q) + 1;
+    len = strlen (realpath);
+    for (i = len; i >= 0; i--)
+      realpath [off + i] = realpath [i];
+
+    /* Copy new segment to realpath */
+    s = q;
+    t = realpath + 1;
+    while (*s)
+      *t++ = *s++;
+
+    /* Stick in separator at beginning of segment. */
+    realpath[0] = DIR_SEPARATOR;
+  }
+
+  /* Split executable name from path */
+  p = strrchr (realpath, DIR_SEPARATOR);
+  *++p = '\0';
+
+  remove_relative_paths (realpath);
+
+  /* Exclude trailing segments to get to the cross root directory */
+  p = realpath;
+  for (i = 0; i< 2 ; i++)
+  {
+    if (!(p = strrchr(realpath, '/')))
+    {
+      free(realpath);
+      goto RET;
+    }
+    *p = '\0';
+  }
+  *ptr = realpath;
+
+RET:
+  free (fullpath);
+  free (linkfile);
+}
+
+/* Replace the initial occurance of PREFIX by the specified prefix */
+
+char *
+replace (char *new_prefix, char *path)
+{
+  char prefix[MAXPATHLEN];
+  int len;
+  int i;
+  char *p;
+
+  strcpy(prefix, SCRIPTDIR);
+
+  /* Find cross dir defined while building */
+  for(i = 0; i < 2; i++)
+  {
+    if (! (p = strrchr(prefix,'/')))
+      return path;
+    *p = '\0';
+  }
+  len = strlen(prefix);
+
+  if (strcmp(new_prefix, prefix) &&
+      ! strncmp (path, prefix, len))
+  {
+    char *new = xmalloc(strlen(new_prefix) +
+                        strlen(path) - len + 1);
+    strcpy(new, new_prefix);
+    strcat(new, path + len);
+    return new;
+  }
+  return path;
+}
+
+static int
+find_family_cpu(char **family_cpu)
+{
+  char *p;
+  int len;
+
+  p = getenv("CROSS_COMPILE");
+  if (p && *p)
+    {
+      p = basename(p);
+      len = strlen(p);
+      *family_cpu = (char *) xmalloc(len + 1);
+      strcpy(*family_cpu, p);
+      if ((*family_cpu)[len - 1] == '-')
+        (*family_cpu)[len - 1] = '\0';
+      return 1;
+    }
+  return 0;
+}
+
+static void
+set_target_dir()
+{
+  char prefix[MAXPATHLEN];
+  char *target_lib;
+  char *target_ulib;
+  char *p;
+  int i, len;
+
+  strcpy(prefix, SCRIPTDIR);
+
+  /* Find cross dir defined while building */
+  for(i = 0; i < 2; i++)
+    {
+      if (! (p = strrchr(prefix,'/')))
+        return;
+      *p = '\0';
+    }
+  len = strlen(prefix);
+
+  target_lib = xmalloc(len + 4 + strlen(family_cpu) + 5);
+  target_ulib = xmalloc(len + 4 + strlen(family_cpu) + 9);
+  sprintf(target_lib,"%s/../%s/lib", prefix, family_cpu);
+  sprintf(target_ulib,"%s/../%s/usr/lib", prefix, family_cpu);
+  ldfile_add_library_path(target_lib, 0, 1);
+  ldfile_add_library_path(target_ulib, 0, 1);
+}
+
