diff -Naur binutils-2.13.90.0.18.orig/gas/config/tc-arm.c binutils-2.13.90.0.18/gas/config/tc-arm.c --- binutils-2.13.90.0.18.orig/gas/config/tc-arm.c Tue Dec 9 13:55:24 2003 +++ binutils-2.13.90.0.18/gas/config/tc-arm.c Tue Dec 9 13:56:15 2003 @@ -39,6 +39,8 @@ #include "dwarf2dbg.h" #endif +extern char * myname; + /* XXX Set this to 1 after the next binutils release */ #define WARN_DEPRECATED 0 @@ -9248,6 +9250,11 @@ mfpu_opt = march_fpu_opt; } + if (mcpu_cpu_opt == -1) + { + set_default_cpu(); + } + if (mfpu_opt == -1) { if (mcpu_cpu_opt == -1) @@ -10518,6 +10525,98 @@ 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, *ep, *tmp = 0; + 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'; + } + + /* try to determine family_cpu using program name */ + p = basename(myname); + ep = strrchr(p, '-'); + if (ep && strchr(p, '_')) + { + len = ep - p; + tmp = (char *) xmalloc(len + 1); + strncpy(tmp, p, len); + tmp[len] = '\0'; + } + + if (! *family_cpu && ! tmp) + { + /* No way to set family_cpu - error */ + return 0; + } + if (tmp) + { + if (*family_cpu) + { + if (strcmp(tmp, *family_cpu)) + { + /* CROSS_COMPILER value is inconsistent with program name */ + return 0; + } + free(tmp); + return 1; + } + *family_cpu = tmp; + setenv("CROSS_COMPILE", tmp, 0); + return 1; + } + + return 1; +} + +/* 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 = 0; + 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 (_("CROSS_COMPILE variable is not set or invalid")); + + 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 -Naur binutils-2.13.90.0.18.orig/gas/config/tc-mips.c binutils-2.13.90.0.18/gas/config/tc-mips.c --- binutils-2.13.90.0.18.orig/gas/config/tc-mips.c Tue Dec 9 13:55:24 2003 +++ binutils-2.13.90.0.18/gas/config/tc-mips.c Tue Dec 9 13:56:15 2003 @@ -77,6 +77,8 @@ #define ECOFF_DEBUGGING 0 #endif +extern char * myname; + int mips_flag_mdebug = -1; #include "ecoff.h" @@ -10721,9 +10723,15 @@ mips_set_architecture (mips_cpu_info_from_isa (file_mips_isa)); } - if (mips_arch_info == 0) - mips_set_architecture (mips_parse_cpu ("default CPU", + if (mips_arch_info == 0) + { + set_default_cpu(); + if (mips_arch_info == 0) + { + mips_set_architecture (mips_parse_cpu ("default CPU", MIPS_CPU_STRING_DEFAULT)); + } + } if (ABI_NEEDS_64BIT_REGS (mips_abi) && !ISA_HAS_64BIT_REGS (mips_opts.isa)) as_bad ("-march=%s is not compatible with the selected ABI", @@ -14311,6 +14319,7 @@ /* MIPS 32 */ { "4kc", 0, ISA_MIPS32, CPU_MIPS32, }, + { "r4kc", 0, ISA_MIPS32, CPU_MIPS32 }, { "4km", 0, ISA_MIPS32, CPU_MIPS32 }, { "4kp", 0, ISA_MIPS32, CPU_MIPS32 }, @@ -14444,6 +14453,108 @@ return NULL; } + +static int find_family_cpu + PARAMS ((char ** ptr)); + +/* set_default_cpu + If the CROSS_COMPILE environment variable is set + set cpu-dependent flags. This function is called only in case + the command options don't define cpu. +*/ +void +set_default_cpu () +{ + char * family_cpu = 0; + int i; + char * cpu; + + struct target_cpu { + char * target_arch; /* name we use in the CROSS_COMPILE variable */ + char *name; /* name registered in mips_cpu_info_table */ + } target_cpu_tbl[] = { + {"4KC", "4kc"} + }; + + if (! find_family_cpu(&family_cpu)) + as_fatal (_("CROSS_COMPILE variable is not set or invalid")); + + 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)) + { + char *name = target_cpu_tbl[i].name; + struct mips_cpu_info *p; + for (p = mips_cpu_info_table; p->name != 0; p++) + { + if (mips_matching_cpu_name_p (p->name, name)) + { + mips_set_architecture(p); + break; + } + } + break; + } + } + } +} + +static int +find_family_cpu (family_cpu) + char **family_cpu; +{ + char *p, *ep, *tmp = 0; + 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'; + } + + /* try to determine family_cpu using program name */ + p = basename(myname); + ep = strrchr(p, '-'); + if (ep && strchr(p, '_')) + { + len = ep - p; + tmp = (char *) xmalloc(len + 1); + strncpy(tmp, p, len); + tmp[len] = '\0'; + } + + if (! *family_cpu && ! tmp) + { + /* No way to set family_cpu - error */ + return 0; + } + if (tmp) + { + if (*family_cpu) + { + if (strcmp(tmp, *family_cpu)) + { + /* CROSS_COMPILER value is inconsistent with program name */ + return 0; + } + free(tmp); + return 1; + } + *family_cpu = tmp; + setenv("CROSS_COMPILE", tmp, 0); + return 1; + } + + return 1; +} static void show (stream, string, col_p, first_p) diff -Naur binutils-2.13.90.0.18.orig/gas/config/tc-ppc.c binutils-2.13.90.0.18/gas/config/tc-ppc.c --- binutils-2.13.90.0.18.orig/gas/config/tc-ppc.c Tue Dec 9 13:55:24 2003 +++ binutils-2.13.90.0.18/gas/config/tc-ppc.c Tue Dec 9 13:56:15 2003 @@ -41,6 +41,8 @@ /* Tell the main code what the endianness is. */ extern int target_big_endian; +extern char *myname; + /* Whether or not, we've set target_big_endian. */ static int set_target_endian = 0; @@ -1097,6 +1099,104 @@ #endif } +static int find_family_cpu + PARAMS ((char ** ptr)); +void set_default_cpu PARAMS ((void)); + +/* 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 = 0; + unsigned int i; + char * cpu; + + struct target_cpu { + char * target_arch; + int flags; + } target_cpu_tbl[] = { + {"4xx", PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_403 | PPC_OPCODE_32}, + {"4xxFP", PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_403 | PPC_OPCODE_32}, + {"74xx", PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32 | PPC_OPCODE_ALTIVEC}, + {"7xx", PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32}, + {"82xx", PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32}, + {"8xx", PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32} + }; + + if (! find_family_cpu(&family_cpu)) + as_fatal (_("CROSS_COMPILE variable is not set or invalid")); + + 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, *ep, *tmp = 0; + 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'; + } + + /* try to determine family_cpu using program name */ + p = basename(myname); + ep = strrchr(p, '-'); + if (ep && strchr(p, '_')) + { + len = ep - p; + tmp = (char *) xmalloc(len + 1); + strncpy(tmp, p, len); + tmp[len] = '\0'; + } + + if (! *family_cpu && ! tmp) + { + /* No way to set family_cpu - error */ + return 0; + } + if (tmp) + { + if (*family_cpu) + { + if (strcmp(tmp, *family_cpu)) + { + /* CROSS_COMPILER value is inconsistent with program name */ + return 0; + } + free(tmp); + return 1; + } + *family_cpu = tmp; + setenv("CROSS_COMPILE", tmp, 0); + return 1; + } + + return 1; +} + /* Set ppc_cpu if it is not already set. */ static void @@ -1106,6 +1206,10 @@ const char *default_cpu = TARGET_CPU; if (ppc_cpu == 0) + { + set_default_cpu(); + } + if (ppc_cpu == 0) { if (ppc_obj64) ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64; @@ -1135,6 +1239,7 @@ ppc_arch () { const char *default_cpu = TARGET_CPU; + ppc_set_cpu (); if ((ppc_cpu & PPC_OPCODE_PPC) != 0) diff -Naur binutils-2.13.90.0.18.orig/ld/Makefile.in binutils-2.13.90.0.18/ld/Makefile.in --- binutils-2.13.90.0.18.orig/ld/Makefile.in Tue Jan 21 19:21:33 2003 +++ binutils-2.13.90.0.18/ld/Makefile.in Tue Dec 9 13:56:15 2003 @@ -2195,7 +2195,7 @@ n=`echo ld | sed '$(transform)'`; \ if [ "$(bindir)/$$n$(EXEEXT)" != "$(tooldir)/bin/ld$(EXEEXT)" ]; then \ rm -f $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \ - ln $(DESTDIR)$(bindir)/$$n$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT) >/dev/null 2>/dev/null \ + ln -s ../../bin/$$n$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT) >/dev/null 2>/dev/null \ || $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) ld-new$(EXEEXT) $(DESTDIR)$(tooldir)/bin/ld$(EXEEXT); \ fi diff -Naur binutils-2.13.90.0.18.orig/ld/ldfile.c binutils-2.13.90.0.18/ld/ldfile.c --- binutils-2.13.90.0.18.orig/ld/ldfile.c Tue Jan 21 19:21:34 2003 +++ binutils-2.13.90.0.18/ld/ldfile.c Tue Dec 9 13:56:15 2003 @@ -36,6 +36,9 @@ #include "ldemul.h" #include "libiberty.h" +extern char *cross_dir; +extern char *replace(char *, char *); + const char *ldfile_input_filename; bfd_boolean ldfile_assumed_script = FALSE; const char *ldfile_output_machine_name = ""; @@ -86,6 +89,8 @@ new->next = NULL; new->name = name; new->cmdline = cmdline; + if (cross_dir && !cmdline) + new->name = replace(cross_dir, name); *search_tail_ptr = new; search_tail_ptr = &new->next; diff -Naur binutils-2.13.90.0.18.orig/ld/ldmain.c binutils-2.13.90.0.18/ld/ldmain.c --- binutils-2.13.90.0.18.orig/ld/ldmain.c Tue Jan 21 19:21:34 2003 +++ binutils-2.13.90.0.18/ld/ldmain.c Tue Dec 9 13:56:15 2003 @@ -48,6 +48,15 @@ #endif #include +#include + +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 *); #ifdef HAVE_SBRK #ifdef NEED_DECLARATION_SBRK @@ -188,6 +197,10 @@ program_name = argv[0]; xmalloc_set_program_name (program_name); + if (!find_family_cpu(&family_cpu)) { + einfo (_("%P%F: CROSS_COMPILE variable is not set or invalid\n")); + } + START_PROGRESS (program_name, 0); bfd_init (); @@ -248,6 +261,8 @@ command_line.check_section_addresses = TRUE; command_line.accept_unknown_input_arch = FALSE; + 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 @@ -349,6 +364,9 @@ 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) @@ -622,6 +640,10 @@ struct stat s; bfd_boolean res; + if (cross_dir) + { + dir = replace(cross_dir, dir); + } dirlen = strlen (dir); /* sizeof counts the terminating NUL. */ buf = (char *) xmalloc (dirlen + sizeof ("/ldscripts")); @@ -1415,3 +1437,288 @@ 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 "//../" ==> "/" */ + 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, *ep, *tmp = 0; + 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'; + } + + /* try to determine family_cpu using program name */ + p = basename(program_name); + ep = strrchr(p, '-'); + if (ep && strchr(p, '_')) + { + len = ep - p; + tmp = (char *) xmalloc(len + 1); + strncpy(tmp, p, len); + tmp[len] = '\0'; + } + + if (! *family_cpu && ! tmp) + { + /* No way to set family_cpu - error */ + return 0; + } + if (tmp) + { + if (*family_cpu) + { + if (strcmp(tmp, *family_cpu)) + { + /* CROSS_COMPILER value is inconsistent with program name */ + /* CROSS_COMPILER value is inconsistent with program name */ + return 0; + } + free(tmp); + return 1; + } + *family_cpu = tmp; + setenv("CROSS_COMPILE", tmp, 0); + return 1; + } + + return 1; +} + +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); + ldfile_add_library_path(target_ulib, 0); +} +