ftp.nice.ch/pub/next/developer/nextsources/cctools.s.tar.gz#/cctools/libstuff/arch.c

This is arch.c in view mode; [Download] [Up]

#include "string.h"
#include <mach/mach.h>
#include "stuff/arch.h"

/*
 * The array of all currently know architecture flags (terminated with an entry
 * with all zeros).  Pointer to this returned with get_arch_flags().
 */
static const struct arch_flag arch_flags[] = {
    { "any",	CPU_TYPE_ANY,	  CPU_SUBTYPE_MULTIPLE },
    { "little",	CPU_TYPE_ANY,	  CPU_SUBTYPE_LITTLE_ENDIAN },
    { "big",	CPU_TYPE_ANY,	  CPU_SUBTYPE_BIG_ENDIAN },
    /* architecture families */
    { "m68k",   CPU_TYPE_MC680x0, CPU_SUBTYPE_MC680x0_ALL },
    { "m98k",   CPU_TYPE_MC98000, CPU_SUBTYPE_MC98000_ALL },
    { "m88k",   CPU_TYPE_MC88000, CPU_SUBTYPE_MC88000_ALL },
    { "i386",   CPU_TYPE_I386,    CPU_SUBTYPE_I386_ALL },
    { "i860",   CPU_TYPE_I860,    CPU_SUBTYPE_I860_ALL },
    { "hppa",   CPU_TYPE_HPPA,    CPU_SUBTYPE_HPPA_ALL },
    { "sparc",	CPU_TYPE_SPARC,   CPU_SUBTYPE_SPARC_ALL },
    /* specific architecture implementations */
    { "m68030", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68030_ONLY },
    { "m68040", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68040 },
    { "i486",   CPU_TYPE_I386,    CPU_SUBTYPE_486 },
    { "i486SX", CPU_TYPE_I386,    CPU_SUBTYPE_486SX },
    { "i586",   CPU_TYPE_I386,    CPU_SUBTYPE_586 },
    { "i586SX", CPU_TYPE_I386,    CPU_SUBTYPE_586SX },
    { "hppa7000", CPU_TYPE_HPPA,  CPU_SUBTYPE_HPPA_7000 },
    { "hppa7100", CPU_TYPE_HPPA,  CPU_SUBTYPE_HPPA_7100 },
    { NULL,	0,		  0 }
};

/*
 * get_arch_from_flag() is passed a name of an architecture flag and returns
 * zero if that flag is not known and non-zero if the flag is known.
 * If the pointer to the arch_flag is not NULL it is filled in with the
 * arch_flag struct that matches the name.
 */
int
get_arch_from_flag(
char *name,
struct arch_flag *arch_flag)
{
    unsigned long i;

	for(i = 0; arch_flags[i].name != NULL; i++){
	    if(strcmp(arch_flags[i].name, name) == 0){
		if(arch_flag != NULL)
		    *arch_flag = arch_flags[i];
		return(1);
	    }
	}
	if(arch_flag != NULL)
	    memset(arch_flag, '\0', sizeof(struct arch_flag));
	return(0);
}

/*
 * get_arch_from_host() gets the architecture from the host this is running on
 * and returns zero if the architecture is not known and zero if the
 * architecture is known.  If the parameters family_arch_flag and
 * specific_arch_flag are not NULL they get fill in with the family
 * architecture and specific architecure for the host.  If the architecture
 * is unknown and the parameters are not NULL then all fields are set to zero.
 */
int
get_arch_from_host(
struct arch_flag *family_arch_flag,
struct arch_flag *specific_arch_flag)
{
    struct host_basic_info host_basic_info;
    unsigned int count;
    kern_return_t r;

	if(family_arch_flag != NULL)
	    memset(family_arch_flag, '\0', sizeof(struct arch_flag));
	if(specific_arch_flag != NULL)
	    memset(specific_arch_flag, '\0', sizeof(struct arch_flag));

	count = HOST_BASIC_INFO_COUNT;
	if((r = host_info(host_self(), HOST_BASIC_INFO,
			  (host_info_t)(&host_basic_info),
			  &count)) != KERN_SUCCESS)
	    return(0);

	if(family_arch_flag != NULL){
	    family_arch_flag->cputype = host_basic_info.cpu_type;
	}
	if(specific_arch_flag != NULL){
	    specific_arch_flag->cputype = host_basic_info.cpu_type;
	    specific_arch_flag->cpusubtype = host_basic_info.cpu_subtype;
	}
	switch(host_basic_info.cpu_type){
	case CPU_TYPE_MC680x0:
	    switch(host_basic_info.cpu_subtype){
	    case CPU_SUBTYPE_MC680x0_ALL:
	    case CPU_SUBTYPE_MC68030_ONLY:
		if(family_arch_flag != NULL){
		    family_arch_flag->name = "m68k";
		    family_arch_flag->cpusubtype = CPU_SUBTYPE_MC680x0_ALL;
		}
		if(specific_arch_flag != NULL){
		    specific_arch_flag->name = "m68030";
		    /* 
		     * There is a "bug" in the kernel for compatiblity that on
		     * an 030 machine host_info() returns cpusubtype
		     * CPU_SUBTYPE_MC680x0_ALL and not CPU_SUBTYPE_MC68030_ONLY.
		     */
		    specific_arch_flag->cpusubtype = CPU_SUBTYPE_MC68030_ONLY;
		}
		return(1);
	    case CPU_SUBTYPE_MC68040:
		if(family_arch_flag != NULL){
		    family_arch_flag->name = "m68k";
		    family_arch_flag->cpusubtype = CPU_SUBTYPE_MC680x0_ALL;
		}
		if(specific_arch_flag != NULL)
		    specific_arch_flag->name = "m68040";
		return(1);
	    }
	    break;
	case CPU_TYPE_MC98000:
	    switch(host_basic_info.cpu_subtype){
	    case CPU_SUBTYPE_MC98000_ALL:
		if(family_arch_flag != NULL){
		    family_arch_flag->name = "m98k";
		    family_arch_flag->cpusubtype = CPU_SUBTYPE_MC98000_ALL;
		}
		if(specific_arch_flag != NULL)
		    specific_arch_flag->name = "m98k";
		return(1);
	    }
	    break;
	case CPU_TYPE_MC88000:
	    switch(host_basic_info.cpu_subtype){
	    case CPU_SUBTYPE_MC88000_ALL:
	    case CPU_SUBTYPE_MC88110:
		if(family_arch_flag != NULL){
		    family_arch_flag->name = "m88k";
		    family_arch_flag->cpusubtype = CPU_SUBTYPE_MC88000_ALL;
		}
		if(specific_arch_flag != NULL)
		    specific_arch_flag->name = "m88k";
		return(1);
	    }
	    break;
	case CPU_TYPE_I386:
	    switch(host_basic_info.cpu_subtype){
	    case CPU_SUBTYPE_I386_ALL:
	    /* case CPU_SUBTYPE_386: same value as above */
		if(family_arch_flag != NULL){
		    family_arch_flag->name = "i386";
		    family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
		}
		if(specific_arch_flag != NULL)
		    specific_arch_flag->name = "i386";
		return(1);
	    case CPU_SUBTYPE_486:
		if(family_arch_flag != NULL){
		    family_arch_flag->name = "i386";
		    family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
		}
		if(specific_arch_flag != NULL)
		    specific_arch_flag->name = "i486";
		return(1);
	    case CPU_SUBTYPE_486SX:
		if(family_arch_flag != NULL){
		    family_arch_flag->name = "i386";
		    family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
		}
		if(specific_arch_flag != NULL)
		    specific_arch_flag->name = "i486SX";
		return(1);
	    case CPU_SUBTYPE_586:
		if(family_arch_flag != NULL){
		    family_arch_flag->name = "i386";
		    family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
		}
		if(specific_arch_flag != NULL)
		    specific_arch_flag->name = "i586";
		return(1);
	    case CPU_SUBTYPE_586SX:
		if(family_arch_flag != NULL){
		    family_arch_flag->name = "i386";
		    family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
		}
		if(specific_arch_flag != NULL)
		    specific_arch_flag->name = "i586SX";
		return(1);
	    }
	    break;
	case CPU_TYPE_I860:
	    switch(host_basic_info.cpu_subtype){
	    case CPU_SUBTYPE_I860_ALL:
	    case CPU_SUBTYPE_I860_860:
		if(family_arch_flag != NULL){
		    family_arch_flag->name = "i860";
		    family_arch_flag->cpusubtype = CPU_SUBTYPE_I860_ALL;
		}
		if(specific_arch_flag != NULL)
		    specific_arch_flag->name = "i860";
		return(1);
	    }
	    break;
	case CPU_TYPE_HPPA:
	    switch(host_basic_info.cpu_subtype){
	    case CPU_SUBTYPE_HPPA_ALL:
	/*  case CPU_SUBTYPE_HPPA_7000: (same constant) */
		if(family_arch_flag != NULL){
		    family_arch_flag->name = "hppa";
		    family_arch_flag->cpusubtype = CPU_SUBTYPE_HPPA_ALL;
		}
		if(specific_arch_flag != NULL)
		    specific_arch_flag->name = "hppa";
		return(1);
	    case CPU_SUBTYPE_HPPA_7100:
		if(family_arch_flag != NULL){
		    family_arch_flag->name = "hppa";
		    family_arch_flag->cpusubtype = CPU_SUBTYPE_HPPA_ALL;
		}
		if(specific_arch_flag != NULL)
		    specific_arch_flag->name = "hppa7100";
		return(1);
	      
	    }
	    break;
	case CPU_TYPE_SPARC:
	    switch(host_basic_info.cpu_subtype){
	    case /*CPU_SUBTYPE_SPARC_ALL*/0:
		if(family_arch_flag != NULL){
		    family_arch_flag->name = "sparc";
		    family_arch_flag->cpusubtype = CPU_SUBTYPE_SPARC_ALL;
		}
		if(specific_arch_flag != NULL)
		    specific_arch_flag->name = "sparc";
		return(1);
	    }
	    break;
	}
	return(0);
}

/*
 * get_arch_flags() returns a pointer to an array of all currently know
 * architecture flags (terminated with an entry with all zeros).
 */
const struct arch_flag *
get_arch_flags(
void)
{
	return(arch_flags);
}

/*
 * get_arch_name_from_types() returns the name of the architecture for the
 * specified cputype and cpusubtype if known.  If unknown it returns a pointer
 * to the string "unknown".
 */
const char *
get_arch_name_from_types(
cpu_type_t cputype,
cpu_subtype_t cpusubtype)
{
    unsigned long i;

	for(i = 0; arch_flags[i].name != NULL; i++){
	    if(arch_flags[i].cputype == cputype &&
	       arch_flags[i].cpusubtype == cpusubtype)
		return(arch_flags[i].name);
	}
	return("unknown");
}

/*
 * get_arch_family_from_cputype() returns the family architecture for the
 * specified cputype if known.  If unknown it returns NULL.
 */
const struct arch_flag *
get_arch_family_from_cputype(
cpu_type_t cputype)
{
    unsigned long i;

	for(i = 0; arch_flags[i].name != NULL; i++){
	    if(arch_flags[i].cputype == cputype)
		return(arch_flags + i);
	}
	return(NULL);
}

/*
 * get_byte_sex_from_flag() returns the byte sex of the architecture for the
 * specified cputype and cpusubtype if known.  If unknown it returns
 * UNKNOWN_BYTE_SEX.  If the bytesex can be determined directly as in the case
 * of reading a magic number from a file that should be done and this routine
 * should not be used as it could be out of date.
 */
enum byte_sex
get_byte_sex_from_flag(
const struct arch_flag *flag)
{
   if(flag->cputype == CPU_TYPE_MC680x0 ||
      flag->cputype == CPU_TYPE_MC88000 ||
      flag->cputype == CPU_TYPE_MC98000 ||
      flag->cputype == CPU_TYPE_HPPA ||
      flag->cputype == CPU_TYPE_SPARC ||
      flag->cputype == CPU_TYPE_I860)
        return BIG_ENDIAN_BYTE_SEX;
    else if(flag->cputype == CPU_TYPE_I386)
        return LITTLE_ENDIAN_BYTE_SEX;
    else
        return UNKNOWN_BYTE_SEX;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.