コード例 #1
0
ファイル: arch.c プロジェクト: mralexgray/MagicHat
/*
 * NXGetArchInfoFromName() is passed a cputype and cpusubtype and returns
 * the matching NXArchInfo struct, or NULL if none is found.  If the
 * cpusubtype is given as CPU_SUBTYPE_MULTIPLE, the first entry that
 * matches the given cputype is returned.  This is the NXArchInfo struct
 * describing the CPU "family".
 */
const
NXArchInfo *
NXGetArchInfoFromCpuType(
cpu_type_t cputype,
cpu_subtype_t cpusubtype)
{
    const NXArchInfo *ai;
    NXArchInfo *q;

    for(ai = ArchInfoTable; ai->name != NULL; ai++)
	if(ai->cputype == cputype &&
	   (cpusubtype == CPU_SUBTYPE_MULTIPLE ||
	    ((ai->cpusubtype & ~CPU_SUBTYPE_MASK) ==
	     (cpusubtype & ~CPU_SUBTYPE_MASK))))
	    return(ai);

    if(cputype == CPU_TYPE_I386){
	q = malloc(sizeof(NXArchInfo));
	for(ai = ArchInfoTable; ai->name != NULL; ai++){
	    if(ai->cputype == cputype){
		*q = *ai;
		break;
	    }
	}
	q->cpusubtype = cpusubtype;
	q->description = malloc(sizeof("Intel family  model ") + 2 + 8);
	if(q->description == NULL)
	    return(NULL);
	sprintf((char *)q->description, "Intel family %u model %u", 
		CPU_SUBTYPE_INTEL_FAMILY(cpusubtype & ~CPU_SUBTYPE_MASK),
		CPU_SUBTYPE_INTEL_MODEL(cpusubtype & ~CPU_SUBTYPE_MASK));
	return((const NXArchInfo *)q);
    }
    else if(cputype == CPU_TYPE_POWERPC){
	q = malloc(sizeof(NXArchInfo));
	for(ai = ArchInfoTable; ai->name != NULL; ai++){
	    if(ai->cputype == cputype){
		*q = *ai;
		break;
	    }
	}
	q->cpusubtype = cpusubtype;
	q->description = malloc(sizeof("PowerPC cpusubtype ") + 10);
	if(q->description == NULL)
	    return(NULL);
	sprintf((char *)q->description, "PowerPC cpusubtype %u", cpusubtype);
	return((const NXArchInfo *)q);
    }

    return(NULL);
}
コード例 #2
0
ファイル: best_arch.c プロジェクト: HoMeCracKeR/otool-ng
/*
 * cpusubtype_findbestarch() is passed a cputype and cpusubtype and a set of
 * fat_arch structs and selects the best one that matches (if any) and returns
 * a pointer to that fat_arch struct (or NULL).  The fat_arch structs must be
 * in the host byte sex and correct such that the fat_archs really points to
 * enough memory for nfat_arch structs.  It is possible that this routine could
 * fail if new cputypes or cpusubtypes are added and an old version of this
 * routine is used.  But if there is an exact match between the cputype and
 * cpusubtype and one of the fat_arch structs this routine will always succeed.
 */
__private_extern__
struct fat_arch *
cpusubtype_findbestarch(
cpu_type_t cputype,
cpu_subtype_t cpusubtype,
struct fat_arch *fat_archs,
uint32_t nfat_archs)
{
    uint32_t i;
    long lowest_family, lowest_model, lowest_index;

	/*
	 * Look for the first exact match.
	 */
	for(i = 0; i < nfat_archs; i++){
	    if(fat_archs[i].cputype == cputype &&
	       (fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
	       (cpusubtype & ~CPU_SUBTYPE_MASK))
		return(fat_archs + i);
	}

	/*
	 * An exact match was not found so find the next best match which is
	 * cputype dependent.
	 */
	switch(cputype){

	/* 64-bit architectures */

	case CPU_TYPE_POWERPC64:
	    /*
	     * An exact match was not found.  So for all the PowerPC64 subtypes
	     * pick the subtype from the following order starting from a subtype
	     * that will work (contains 64-bit instructions or altivec if
	     * needed):
	     *	970 (currently only the one 64-bit subtype)
	     * For an unknown subtype pick only the ALL type if it exists.
	     */
	    switch(cpusubtype & ~CPU_SUBTYPE_MASK){
	    case CPU_SUBTYPE_POWERPC_ALL:
		/*
		 * The CPU_SUBTYPE_POWERPC_ALL is only used by the development
		 * environment tools when building a generic ALL type binary.
		 * In the case of a non-exact match we pick the most current
		 * processor.
		 */
	    case CPU_SUBTYPE_POWERPC_970:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_POWERPC_970)
			return(fat_archs + i);
		}
	    default:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_POWERPC_ALL)
			return(fat_archs + i);
		}
	    }
	    break;

	case CPU_TYPE_X86_64:
	    /*
	     * We have no subtypes for x86-64, so treat all cases the same here.
	     */
	    switch(cpusubtype & ~CPU_SUBTYPE_MASK){
	    default:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_I386_ALL)
			return(fat_archs + i);
		}
	    }
	    break;

	/* 32-bit architectures */

	case CPU_TYPE_I386:
	    switch(cpusubtype & ~CPU_SUBTYPE_MASK){
	    default:
		/*
		 * Intel cpusubtypes after the pentium (same as 586) are handled
		 * such that they require an exact match or they can use the
		 * pentium.  If that is not found call into the loop for the
		 * earilier subtypes.
		 */
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_PENT)
			return(fat_archs + i);
		}
	    case CPU_SUBTYPE_PENT:
	    case CPU_SUBTYPE_486SX:
		/*
		 * Since an exact match as not found look for the i486 else
		 * break into the loop to look for the i386_ALL.
		 */
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_486)
			return(fat_archs + i);
		}
		break;
	    case CPU_SUBTYPE_I386_ALL:
	    /* case CPU_SUBTYPE_I386: same as above */
	    case CPU_SUBTYPE_486:
		break;
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_I386_ALL)
		    return(fat_archs + i);
	    }

	    /*
	     * A match failed, promote as little as possible.
	     */
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_486)
		    return(fat_archs + i);
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_486SX)
		    return(fat_archs + i);
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_586)
		    return(fat_archs + i);
	    }
	    /*
	     * Now look for the lowest family and in that the lowest model.
	     */
	    lowest_family = CPU_SUBTYPE_INTEL_FAMILY_MAX + 1;
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(CPU_SUBTYPE_INTEL_FAMILY(fat_archs[i].cpusubtype &
					    ~CPU_SUBTYPE_MASK) <
		   lowest_family)
		    lowest_family = CPU_SUBTYPE_INTEL_FAMILY(
				fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
	    }
	    /* if no intel cputypes found return NULL */
	    if(lowest_family == CPU_SUBTYPE_INTEL_FAMILY_MAX + 1)
		return(NULL);
	    lowest_model = LONG_MAX;
	    lowest_index = -1;
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(CPU_SUBTYPE_INTEL_FAMILY(fat_archs[i].cpusubtype &
					    ~CPU_SUBTYPE_MASK) ==
		   lowest_family){
		    if(CPU_SUBTYPE_INTEL_MODEL(fat_archs[i].cpusubtype &
					       ~CPU_SUBTYPE_MASK) <
		       lowest_model){
		        lowest_model = CPU_SUBTYPE_INTEL_MODEL(
				fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
			lowest_index = i;
		    }
		}
	    }
	    return(fat_archs + lowest_index);
	case CPU_TYPE_MC680x0:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_MC680x0_ALL)
		    return(fat_archs + i);
	    }
	    /*
	     * Try to promote if starting from CPU_SUBTYPE_MC680x0_ALL and
	     * favor the CPU_SUBTYPE_MC68040 over the CPU_SUBTYPE_MC68030_ONLY.
	     */
	    if((cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC680x0_ALL){
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_MC68040)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_MC68030_ONLY)
			return(fat_archs + i);
		}
	    }
	    break;
	case CPU_TYPE_POWERPC:
	    /*
	     * An exact match as not found.  So for all the PowerPC subtypes
	     * pick the subtype from the following order starting from a subtype
	     * that will work (contains 64-bit instructions or altivec if
	     * needed):
	     *	970, 7450, 7400, 750, 604e, 604, 603ev, 603e, 603, ALL
	     * Note the 601 is NOT in the list above.  It is only picked via
	     * an exact match.  For an unknown subtype pick only the ALL type if
	     * it exists.
	     */
	    switch(cpusubtype & ~CPU_SUBTYPE_MASK){
	    case CPU_SUBTYPE_POWERPC_ALL:
		/*
		 * The CPU_SUBTYPE_POWERPC_ALL is only used by the development
		 * environment tools when building a generic ALL type binary.
		 * In the case of a non-exact match we pick the most current
		 * processor.
		 */
	    case CPU_SUBTYPE_POWERPC_970:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_POWERPC_970)
			return(fat_archs + i);
		}
	    case CPU_SUBTYPE_POWERPC_7450:
	    case CPU_SUBTYPE_POWERPC_7400:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_POWERPC_7450)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_POWERPC_7400)
			return(fat_archs + i);
		}
	    case CPU_SUBTYPE_POWERPC_750:
	    case CPU_SUBTYPE_POWERPC_604e:
	    case CPU_SUBTYPE_POWERPC_604:
	    case CPU_SUBTYPE_POWERPC_603ev:
	    case CPU_SUBTYPE_POWERPC_603e:
	    case CPU_SUBTYPE_POWERPC_603:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_POWERPC_750)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_POWERPC_604e)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK)
		        == CPU_SUBTYPE_POWERPC_604)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_POWERPC_603ev)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_POWERPC_603e)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_POWERPC_603)
			return(fat_archs + i);
		}
	    default:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_POWERPC_ALL)
			return(fat_archs + i);
		}
	    }
	    break;
	case CPU_TYPE_VEO:
	    /*
	     * An exact match was not found.  So for the VEO subtypes if VEO1
	     * or VEO3 is wanted then VEO2 can be used.  If VEO4 is wanted then
	     * either VEO2 or (preferably) VEO3 can be used.  But if VEO2 is
	     * wanted only VEO2 can be used.  Any unknown values don't match.
	     */
	    switch(cpusubtype & ~CPU_SUBTYPE_MASK){
	    case CPU_SUBTYPE_VEO_1:
	    case CPU_SUBTYPE_VEO_3:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_VEO_2)
			return(fat_archs + i);
		}
	    case CPU_SUBTYPE_VEO_4:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_VEO_3)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_VEO_2)
			return(fat_archs + i);
		}
	    }
	    break;
	case CPU_TYPE_MC88000:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_MC88000_ALL)
		    return(fat_archs + i);
	    }
	    break;
	case CPU_TYPE_I860:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_I860_ALL)
		    return(fat_archs + i);
	    }
	    break;
	case CPU_TYPE_HPPA:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_HPPA_ALL)
		    return(fat_archs + i);
	    }
	    break;
	case CPU_TYPE_SPARC:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_SPARC_ALL)
		    return(fat_archs + i);
	    }
	    break;
	case CPU_TYPE_ARM:
	    /*
	     * If it weren't for xscale, we could have a simple
	     * heirarchy like ppc.  However, xscale has instructions
	     * which aren't present on v5 or v6.  Here's the acceptable
	     * fat slices for each ARM subtype, for most to least
	     * preferred:
	     *   v4t: v4t, ALL
	     *   v5: v5, v4t, ALL
	     *   xscale: xscale, v4t, ALL
	     *   v6: v7, v6, v5, v4t, ALL
	     *   ALL: v6, v5, xscale, v4t, ALL
	     */
	    if(cpusubtype == CPU_SUBTYPE_ARM_ALL ||
	       cpusubtype == CPU_SUBTYPE_ARM_V7K){
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype == cputype &&
		       fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V7S)
			return(fat_archs + i);
		}
	    }
	    if(cpusubtype == CPU_SUBTYPE_ARM_ALL ||
	       cpusubtype == CPU_SUBTYPE_ARM_V7S){
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype == cputype &&
		       fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V7F)
			return(fat_archs + i);
		}
	    }
	    if(cpusubtype == CPU_SUBTYPE_ARM_ALL ||
	       cpusubtype == CPU_SUBTYPE_ARM_V7F){
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype == cputype &&
		       fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V7)
			return(fat_archs + i);
		}
	    }
	    if(cpusubtype == CPU_SUBTYPE_ARM_ALL ||
	       cpusubtype == CPU_SUBTYPE_ARM_V7 ||
	       cpusubtype == CPU_SUBTYPE_ARM_V6){
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype == cputype &&
		       fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V6)
			return(fat_archs + i);
		}
	    }
	    if(cpusubtype == CPU_SUBTYPE_ARM_ALL ||
	       cpusubtype == CPU_SUBTYPE_ARM_V6 ||
	       cpusubtype == CPU_SUBTYPE_ARM_V5TEJ){
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype == cputype &&
		       fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V5TEJ)
			return(fat_archs + i);
		}
	    }
	    if(cpusubtype == CPU_SUBTYPE_ARM_ALL ||
	       cpusubtype == CPU_SUBTYPE_ARM_XSCALE){
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype == cputype &&
		       fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_XSCALE)
			return(fat_archs + i);
		}
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype == cputype &&
		   fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V4T)
		    return(fat_archs + i);
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype == cputype &&
		   fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V6M)
		    return(fat_archs + i);
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype == cputype &&
		   fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V7M)
		    return(fat_archs + i);
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype == cputype &&
		   fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_V7EM)
		    return(fat_archs + i);
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype == cputype &&
		   fat_archs[i].cpusubtype == CPU_SUBTYPE_ARM_ALL)
		    return(fat_archs + i);
	    }

	default:
	    return(NULL);
	}
	return(NULL);
}
コード例 #3
0
ファイル: best_arch.c プロジェクト: OpenDarwin-CVS/SEDarwin
/*
 * cpusubtype_findbestarch() is passed a cputype and cpusubtype and a set of
 * fat_arch structs and selects the best one that matches (if any) and returns
 * a pointer to that fat_arch struct (or NULL).  The fat_arch structs must be
 * in the host byte sex and correct such that the fat_archs really points to
 * enough memory for nfat_arch structs.  It is possible that this routine could
 * fail if new cputypes or cpusubtypes are added and an old version of this
 * routine is used.  But if there is an exact match between the cputype and
 * cpusubtype and one of the fat_arch structs this routine will always succeed.
 */
__private_extern__
struct fat_arch *
cpusubtype_findbestarch(
cpu_type_t cputype,
cpu_subtype_t cpusubtype,
struct fat_arch *fat_archs,
unsigned long nfat_archs)
{
    unsigned long i;
    long lowest_family, lowest_model, lowest_index;

	/*
	 * Look for the first exact match.
	 */
	for(i = 0; i < nfat_archs; i++){
	    if(fat_archs[i].cputype == cputype &&
	       fat_archs[i].cpusubtype == cpusubtype)
		return(fat_archs + i);
	}

	/*
	 * An exact match was not found so find the next best match which is
	 * cputype dependent.
	 */
	switch(cputype){
	case CPU_TYPE_I386:
	    switch(cpusubtype){
	    default:
		/*
		 * Intel cpusubtypes after the pentium (same as 586) are handled
		 * such that they require an exact match or they can use the
		 * pentium.  If that is not found call into the loop for the
		 * earilier subtypes.
		 */
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_PENT)
			return(fat_archs + i);
		}
	    case CPU_SUBTYPE_PENT:
	    case CPU_SUBTYPE_486SX:
		/*
		 * Since an exact match as not found look for the i486 else
		 * break into the loop to look for the i386_ALL.
		 */
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_486)
			return(fat_archs + i);
		}
		break;
	    case CPU_SUBTYPE_I386_ALL:
	    /* case CPU_SUBTYPE_I386: same as above */
	    case CPU_SUBTYPE_486:
		break;
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(fat_archs[i].cpusubtype == CPU_SUBTYPE_I386_ALL)
		    return(fat_archs + i);
	    }

	    /*
	     * A match failed, promote as little as possible.
	     */
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(fat_archs[i].cpusubtype == CPU_SUBTYPE_486)
		    return(fat_archs + i);
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(fat_archs[i].cpusubtype == CPU_SUBTYPE_486SX)
		    return(fat_archs + i);
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(fat_archs[i].cpusubtype == CPU_SUBTYPE_586)
		    return(fat_archs + i);
	    }
	    /*
	     * Now look for the lowest family and in that the lowest model.
	     */
	    lowest_family = CPU_SUBTYPE_INTEL_FAMILY_MAX + 1;
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(CPU_SUBTYPE_INTEL_FAMILY(fat_archs[i].cpusubtype) <
		   lowest_family)
		    lowest_family = CPU_SUBTYPE_INTEL_FAMILY(
					fat_archs[i].cpusubtype);
	    }
	    /* if no intel cputypes found return NULL */
	    if(lowest_family == CPU_SUBTYPE_INTEL_FAMILY_MAX + 1)
		return(NULL);
	    lowest_model = ULONG_MAX;
	    lowest_index = -1;
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(CPU_SUBTYPE_INTEL_FAMILY(fat_archs[i].cpusubtype) ==
		   lowest_family){
		    if(CPU_SUBTYPE_INTEL_MODEL(fat_archs[i].cpusubtype) <
		       lowest_model){
		        lowest_model = CPU_SUBTYPE_INTEL_MODEL(
					fat_archs[i].cpusubtype);
			lowest_index = i;
		    }
		}
	    }
	    return(fat_archs + lowest_index);
	case CPU_TYPE_MC680x0:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(fat_archs[i].cpusubtype == CPU_SUBTYPE_MC680x0_ALL)
		    return(fat_archs + i);
	    }
	    /*
	     * Try to promote if starting from CPU_SUBTYPE_MC680x0_ALL and
	     * favor the CPU_SUBTYPE_MC68040 over the CPU_SUBTYPE_MC68030_ONLY.
	     */
	    if(cpusubtype == CPU_SUBTYPE_MC680x0_ALL){
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_MC68040)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_MC68030_ONLY)
			return(fat_archs + i);
		}
	    }
	    break;
	case CPU_TYPE_POWERPC:
	    /*
	     * An exact match as not found.  So for all the PowerPC subtypes
	     * pick the subtype from the following order starting from a subtype
	     * that will work (contains 64-bit instructions or altivec if
	     * needed):
	     *	970, 7450, 7400, 750, 604e, 604, 603ev, 603e, 603, ALL
	     * Note the 601 is NOT in the list above.  It is only picked via
	     * an exact match.  For an unknown subtype pick only the ALL type if
	     * it exists.
	     */
	    switch(cpusubtype){
	    case CPU_SUBTYPE_POWERPC_ALL:
		/*
		 * The CPU_SUBTYPE_POWERPC_ALL is only used by the development
		 * environment tools when building a generic ALL type binary.
		 * In the case of a non-exact match we pick the most current
		 * processor.
		 */
	    case CPU_SUBTYPE_POWERPC_970:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_POWERPC_970)
			return(fat_archs + i);
		}
	    case CPU_SUBTYPE_POWERPC_7450:
	    case CPU_SUBTYPE_POWERPC_7400:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_POWERPC_7450)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_POWERPC_7400)
			return(fat_archs + i);
		}
	    case CPU_SUBTYPE_POWERPC_750:
	    case CPU_SUBTYPE_POWERPC_604e:
	    case CPU_SUBTYPE_POWERPC_604:
	    case CPU_SUBTYPE_POWERPC_603ev:
	    case CPU_SUBTYPE_POWERPC_603e:
	    case CPU_SUBTYPE_POWERPC_603:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_POWERPC_750)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_POWERPC_604e)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_POWERPC_604)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_POWERPC_603ev)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_POWERPC_603e)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_POWERPC_603)
			return(fat_archs + i);
		}
	    default:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_POWERPC_ALL)
			return(fat_archs + i);
		}
	    }
	    break;
	case CPU_TYPE_VEO:
	    /*
	     * An exact match was not found.  So for the VEO subtypes if VEO1
	     * is wanted then VEO2 can be used.  But if VEO2 is wanted only
	     * VEO2 can be used.  Any unknown values don't match.
	     */
	    switch(cpusubtype){
	    case CPU_SUBTYPE_VEO_1:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype == CPU_SUBTYPE_VEO_2)
			return(fat_archs + i);
		}
	    }
	    break;
	case CPU_TYPE_MC88000:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(fat_archs[i].cpusubtype == CPU_SUBTYPE_MC88000_ALL)
		    return(fat_archs + i);
	    }
	    break;
	case CPU_TYPE_I860:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(fat_archs[i].cpusubtype == CPU_SUBTYPE_I860_ALL)
		    return(fat_archs + i);
	    }
	    break;
	case CPU_TYPE_HPPA:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(fat_archs[i].cpusubtype == CPU_SUBTYPE_HPPA_ALL)
		    return(fat_archs + i);
	    }
	    break;
	case CPU_TYPE_SPARC:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(fat_archs[i].cpusubtype == CPU_SUBTYPE_SPARC_ALL)
		    return(fat_archs + i);
	    }
	    break;
	default:
	    return(NULL);
	}
	return(NULL);
}
コード例 #4
0
ファイル: best_arch.c プロジェクト: OpenDarwin-CVS/SEDarwin
/*
 * cpusubtype_combine() returns the resulting cpusubtype when combining two
 * differnet cpusubtypes for the specified cputype.  If the two cpusubtypes
 * can't be combined (the specific subtypes are mutually exclusive) -1 is
 * returned indicating it is an error to combine them.  This can also fail and
 * return -1 if new cputypes or cpusubtypes are added and an old version of
 * this routine is used.  But if the cpusubtypes are the same they can always
 * be combined and this routine will return the cpusubtype pass in.
 */
__private_extern__
cpu_subtype_t
cpusubtype_combine(
cpu_type_t cputype,
cpu_subtype_t cpusubtype1,
cpu_subtype_t cpusubtype2)
{
	if(cpusubtype1 == cpusubtype2)
	    return(cpusubtype1);

	switch(cputype){
	case CPU_TYPE_I386:
	    /*
	     * For compatiblity with pre-Rhapsody CR1 systems the subtypes that
	     * previously existed are handled the same as before.  So going in
	     * we know we don't have an exact match because of the test done
	     * at the beginning of the routine.
	     */
	    if((cpusubtype1 == CPU_SUBTYPE_I386_ALL ||
	        /* cpusubtype1 == CPU_SUBTYPE_386 || same as above */
	        cpusubtype1 == CPU_SUBTYPE_486 ||
	        cpusubtype1 == CPU_SUBTYPE_486SX ||
	        cpusubtype1 == CPU_SUBTYPE_586) &&
	       (cpusubtype2 == CPU_SUBTYPE_I386_ALL ||
	        /* cpusubtype2 == CPU_SUBTYPE_386 || same as above */
	        cpusubtype2 == CPU_SUBTYPE_486 ||
	        cpusubtype2 == CPU_SUBTYPE_486SX ||
	        cpusubtype2 == CPU_SUBTYPE_586)){
		/* return the highest subtype of the two */
		if(cpusubtype1 == CPU_SUBTYPE_586 ||
		   cpusubtype2 == CPU_SUBTYPE_586)
		    return(CPU_SUBTYPE_586);
		if(cpusubtype1 == CPU_SUBTYPE_486SX ||
		   cpusubtype2 == CPU_SUBTYPE_486SX)
		    return(CPU_SUBTYPE_486SX);
		if(cpusubtype1 == CPU_SUBTYPE_486 ||
		   cpusubtype2 == CPU_SUBTYPE_486)
		    return(CPU_SUBTYPE_486);
		break; /* logically can't get here */
	    }
	    /*
	     * If either is a MODEL_ALL type select the one with the highest
	     * family type.  Note that only the old group of subtypes (ALL, 386,
	     * 486, 486SX, 586) can ever have MODEL_ALL (a model number of
	     * zero).  Since the cases both subtypes being in the old group are
	     * handled above this makes the the highest family type the one that
	     * is not MODEL_ALL.
	     */
	    if(CPU_SUBTYPE_INTEL_MODEL(cpusubtype1) ==
	       CPU_SUBTYPE_INTEL_MODEL_ALL)
		return(cpusubtype2);
	    if(CPU_SUBTYPE_INTEL_MODEL(cpusubtype2) ==
	       CPU_SUBTYPE_INTEL_MODEL_ALL)
		return(cpusubtype1);
	    /*
	     * For all other families and models they must match exactly to
	     * combine and since that test was done at the start of this routine
	     * we know these do not match and do not combine.
	     */
	    return((cpu_subtype_t)-1);
	    break; /* logically can't get here */

	case CPU_TYPE_MC680x0:
	    if(cpusubtype1 != CPU_SUBTYPE_MC680x0_ALL &&
	       cpusubtype1 != CPU_SUBTYPE_MC68030_ONLY &&
	       cpusubtype1 != CPU_SUBTYPE_MC68040)
		return((cpu_subtype_t)-1);
	    if(cpusubtype2 != CPU_SUBTYPE_MC680x0_ALL &&
	       cpusubtype2 != CPU_SUBTYPE_MC68030_ONLY &&
	       cpusubtype2 != CPU_SUBTYPE_MC68040)
		return((cpu_subtype_t)-1);

	    if(cpusubtype1 == CPU_SUBTYPE_MC68030_ONLY &&
	       cpusubtype2 == CPU_SUBTYPE_MC68040)
		return((cpu_subtype_t)-1);
	    if(cpusubtype1 == CPU_SUBTYPE_MC68040 &&
	       cpusubtype2 == CPU_SUBTYPE_MC68030_ONLY)
		return((cpu_subtype_t)-1);

	    if(cpusubtype1 == CPU_SUBTYPE_MC68030_ONLY ||
	       cpusubtype2 == CPU_SUBTYPE_MC68030_ONLY)
		return(CPU_SUBTYPE_MC68030_ONLY);

	    if(cpusubtype1 == CPU_SUBTYPE_MC68040 ||
	       cpusubtype2 == CPU_SUBTYPE_MC68040)
		return(CPU_SUBTYPE_MC68040);
	    break; /* logically can't get here */

	case CPU_TYPE_POWERPC:
	    /*
	     * Combining with the ALL type becomes the other type. Combining
	     * anything with the 601 becomes 601.  All other non exact matches
	     * combine to the higher value subtype.
	     */
	    if(cpusubtype1 == CPU_SUBTYPE_POWERPC_ALL)
		return(cpusubtype2);
	    if(cpusubtype2 == CPU_SUBTYPE_POWERPC_ALL)
		return(cpusubtype1);

	    if(cpusubtype1 == CPU_SUBTYPE_POWERPC_601 ||
	       cpusubtype2 == CPU_SUBTYPE_POWERPC_601)
		return(CPU_SUBTYPE_POWERPC_601);

	    if(cpusubtype1 > cpusubtype2)
		return(cpusubtype1);
	    else
		return(cpusubtype2);
	    break; /* logically can't get here */

	case CPU_TYPE_VEO:
	    /*
	     * Combining VEO1 with VEO2 returns VEO1.  Any unknown values don't
	     * combine.
	     */
	    if(cpusubtype1 == CPU_SUBTYPE_VEO_1 &&
	       cpusubtype2 == CPU_SUBTYPE_VEO_2)
		return(CPU_SUBTYPE_VEO_1);
	    if(cpusubtype1 == CPU_SUBTYPE_VEO_2 &&
	       cpusubtype2 == CPU_SUBTYPE_VEO_1)
		return(CPU_SUBTYPE_VEO_1);
	    return((cpu_subtype_t)-1);
	    break; /* logically can't get here */

	case CPU_TYPE_MC88000:
	    if(cpusubtype1 != CPU_SUBTYPE_MC88000_ALL &&
	       cpusubtype1 != CPU_SUBTYPE_MC88110)
		return((cpu_subtype_t)-1);
	    if(cpusubtype2 != CPU_SUBTYPE_MC88000_ALL &&
	       cpusubtype2 != CPU_SUBTYPE_MC88110)
		return((cpu_subtype_t)-1);

	    if(cpusubtype1 == CPU_SUBTYPE_MC88110 ||
	       cpusubtype2 == CPU_SUBTYPE_MC88110)
		return(CPU_SUBTYPE_MC88110);

	    break; /* logically can't get here */

	case CPU_TYPE_I860:
	    if(cpusubtype1 != CPU_SUBTYPE_I860_ALL &&
	       cpusubtype1 != CPU_SUBTYPE_I860_860)
		return((cpu_subtype_t)-1);
	    if(cpusubtype2 != CPU_SUBTYPE_I860_ALL &&
	       cpusubtype2 != CPU_SUBTYPE_I860_860)
		return((cpu_subtype_t)-1);

	    if(cpusubtype1 == CPU_SUBTYPE_I860_860 ||
	       cpusubtype2 == CPU_SUBTYPE_I860_860)
		return(CPU_SUBTYPE_I860_860);
	    break; /* logically can't get here */

	case CPU_TYPE_HPPA:
	    if(cpusubtype1 != CPU_SUBTYPE_HPPA_ALL &&
	       cpusubtype1 != CPU_SUBTYPE_HPPA_7100LC)
		return((cpu_subtype_t)-1);
	    if(cpusubtype2 != CPU_SUBTYPE_HPPA_ALL &&
	       cpusubtype2 != CPU_SUBTYPE_HPPA_7100LC)
		return((cpu_subtype_t)-1);

	    return(CPU_SUBTYPE_HPPA_7100LC);
	    break; /* logically can't get here */

	case CPU_TYPE_SPARC:
	    if(cpusubtype1 != CPU_SUBTYPE_SPARC_ALL)
			return((cpu_subtype_t)-1);
	    if(cpusubtype2 != CPU_SUBTYPE_SPARC_ALL)
			return((cpu_subtype_t)-1);
	    break; /* logically can't get here */

	default:
	    return((cpu_subtype_t)-1);
	}
	return((cpu_subtype_t)-1); /* logically can't get here */
}
コード例 #5
0
ファイル: get_arch_from_host.c プロジェクト: disigma/cctools
/*
 * 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.
 */
__private_extern__
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;
    mach_port_t my_mach_host_self;

    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;
    my_mach_host_self = mach_host_self();
    if((r = host_info(my_mach_host_self, HOST_BASIC_INFO,
                      (host_info_t)(&host_basic_info),
                      &count)) != KERN_SUCCESS) {
        mach_port_deallocate(mach_task_self(), my_mach_host_self);
        return(0);
    }
    mach_port_deallocate(mach_task_self(), my_mach_host_self);

    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_POWERPC:
        switch(host_basic_info.cpu_subtype) {
        case CPU_SUBTYPE_POWERPC_ALL:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "ppc";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "ppc";
            return(1);
        case CPU_SUBTYPE_POWERPC_601:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "ppc";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "ppc601";
            return(1);
        case CPU_SUBTYPE_POWERPC_603:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "ppc";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "ppc603";
            return(1);
        case CPU_SUBTYPE_POWERPC_603e:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "ppc";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "ppc603e";
            return(1);
        case CPU_SUBTYPE_POWERPC_603ev:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "ppc";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "ppc603ev";
            return(1);
        case CPU_SUBTYPE_POWERPC_604:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "ppc";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "ppc604";
            return(1);
        case CPU_SUBTYPE_POWERPC_604e:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "ppc";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "ppc604e";
            return(1);
        case CPU_SUBTYPE_POWERPC_750:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "ppc";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "ppc750";
            return(1);
        case CPU_SUBTYPE_POWERPC_7400:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "ppc";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "ppc7400";
            return(1);
        case CPU_SUBTYPE_POWERPC_7450:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "ppc";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "ppc7450";
            return(1);
        case CPU_SUBTYPE_POWERPC_970:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "ppc";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "ppc970";
            return(1);
        default:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "ppc";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
            }
            if(specific_arch_flag != NULL) {
                specific_arch_flag->name =
                    savestr("PowerPC cpusubtype 1234567890");
                if(specific_arch_flag->name != NULL)
                    sprintf(specific_arch_flag->name,
                            "PowerPC cpusubtype %u",
                            host_basic_info.cpu_subtype);
            }
            return(1);
        }
        break;
    case CPU_TYPE_VEO:
        switch(host_basic_info.cpu_subtype) {
        case CPU_SUBTYPE_VEO_1:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "veo";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "veo1";
            return(1);
        case CPU_SUBTYPE_VEO_2:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "veo";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "veo2";
            return(1);
        case CPU_SUBTYPE_VEO_3:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "veo";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "veo3";
            return(1);
        case CPU_SUBTYPE_VEO_4:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "veo";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "veo4";
            return(1);
        default:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "veo";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL;
            }
            if(specific_arch_flag != NULL) {
                specific_arch_flag->name =
                    savestr("VEO cpusubtype 1234567890");
                sprintf(specific_arch_flag->name,
                        "VEO cpusubtype %u",
                        host_basic_info.cpu_subtype);
            }
            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_PENT: /* same as 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 = "pentium";
            return(1);
        case CPU_SUBTYPE_PENTPRO:
            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 = "pentpro";
            return(1);
        case CPU_SUBTYPE_PENTII_M3:
            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 = "pentIIm3";
            return(1);
        case CPU_SUBTYPE_PENTII_M5:
            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 = "pentIIm5";
            return(1);
        case CPU_SUBTYPE_PENTIUM_4:
            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 = "pentium4";
            return(1);
        default:
            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 =
                    savestr("Intel family 12 model 12345678");
                if(specific_arch_flag->name != NULL)
                    sprintf(specific_arch_flag->name,
                            "Intel family %u model %u",
                            CPU_SUBTYPE_INTEL_FAMILY(host_basic_info.cpu_subtype),
                            CPU_SUBTYPE_INTEL_MODEL(host_basic_info.cpu_subtype));
            }
            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:
            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_7100LC:
            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 = "hppa7100LC";
            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;
    case CPU_TYPE_ARM:
        switch(host_basic_info.cpu_subtype) {
        case CPU_SUBTYPE_ARM_ALL:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "arm";
            return(1);
        case CPU_SUBTYPE_ARM_V4T:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "armv4t";
            return(1);
        case CPU_SUBTYPE_ARM_V5TEJ:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "armv5";
            return(1);
        case CPU_SUBTYPE_ARM_XSCALE:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "xscale";
            return(1);
        case CPU_SUBTYPE_ARM_V6:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "armv6";
            return(1);
        case CPU_SUBTYPE_ARM_V6M:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "armv6m";
            return(1);
        case CPU_SUBTYPE_ARM_V7:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "armv7";
            return(1);
        case CPU_SUBTYPE_ARM_V7F:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "armv7f";
            return(1);
        case CPU_SUBTYPE_ARM_V7S:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "armv7s";
            return(1);
        case CPU_SUBTYPE_ARM_V7K:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "armv7k";
            return(1);
        case CPU_SUBTYPE_ARM_V7M:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "armv7m";
            return(1);
        case CPU_SUBTYPE_ARM_V7EM:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "armv7em";
            return(1);
        }
        break;
    case CPU_TYPE_ARM64:
        switch(host_basic_info.cpu_subtype) {
        case CPU_SUBTYPE_ARM64_ALL:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm64";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM64_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "arm64";
            return(1);
        case CPU_SUBTYPE_ARM64_V8:
            if(family_arch_flag != NULL) {
                family_arch_flag->name = "arm64";
                family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM64_ALL;
            }
            if(specific_arch_flag != NULL)
                specific_arch_flag->name = "arm64v8";
            return(1);
        }
        break;
    }
    return(0);
}
コード例 #6
0
ファイル: machine.c プロジェクト: fawzi/oldTango
uint extractCpuSubtypeIntelModel(uint x){
    return CPU_SUBTYPE_INTEL_MODEL(x);
}
コード例 #7
0
ファイル: arch.c プロジェクト: mralexgray/MagicHat
/*
 * NXFindBestFatArch() is passed a cputype and cpusubtype and a set of
 * fat_arch structs and selects the best one that matches (if any) and returns
 * a pointer to that fat_arch struct (or NULL).  The fat_arch structs must be
 * in the host byte order and correct such that the fat_archs really points to
 * enough memory for nfat_arch structs.  It is possible that this routine could
 * fail if new cputypes or cpusubtypes are added and an old version of this
 * routine is used.  But if there is an exact match between the cputype and
 * cpusubtype and one of the fat_arch structs this routine will always succeed.
 */
struct fat_arch *
NXFindBestFatArch(
cpu_type_t cputype,
cpu_subtype_t cpusubtype,
struct fat_arch *fat_archs,
uint32_t nfat_archs)
{
    uint32_t i;
    int32_t lowest_family, lowest_model, lowest_index;

	/*
	 * Look for the first exact match.
	 */
	for(i = 0; i < nfat_archs; i++){
	    if(fat_archs[i].cputype == cputype &&
	       (fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		(cpusubtype & ~CPU_SUBTYPE_MASK))
		return(fat_archs + i);
	}

	/*
	 * An exact match was not found so find the next best match which is
	 * cputype dependent.
	 */
	switch(cputype){
	case CPU_TYPE_I386:
	    switch(cpusubtype & ~CPU_SUBTYPE_MASK){
	    default:
		/*
		 * Intel cpusubtypes after the pentium (same as 586) are handled
		 * such that they require an exact match or they can use the
		 * pentium.  If that is not found call into the loop for the
		 * earilier subtypes.
		 */
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_PENT)
			return(fat_archs + i);
		}
	    case CPU_SUBTYPE_PENT:
	    case CPU_SUBTYPE_486SX:
		/*
		 * Since an exact match as not found look for the i486 else
		 * break into the loop to look for the i386_ALL.
		 */
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_486)
			return(fat_archs + i);
		}
		break;
	    case CPU_SUBTYPE_I386_ALL:
	    /* case CPU_SUBTYPE_I386: same as above */
	    case CPU_SUBTYPE_486:
		break;
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		    CPU_SUBTYPE_I386_ALL)
		    return(fat_archs + i);
	    }

	    /*
	     * A match failed, promote as little as possible.
	     */
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_486)
		    return(fat_archs + i);
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_486SX)
		    return(fat_archs + i);
	    }
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_586)
		    return(fat_archs + i);
	    }
	    /*
	     * Now look for the lowest family and in that the lowest model.
	     */
	    lowest_family = CPU_SUBTYPE_INTEL_FAMILY_MAX + 1;
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(CPU_SUBTYPE_INTEL_FAMILY(fat_archs[i].cpusubtype &
					    ~CPU_SUBTYPE_MASK) < lowest_family)
		    lowest_family = CPU_SUBTYPE_INTEL_FAMILY(
				fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
	    }
	    /* if no intel cputypes found return NULL */
	    if(lowest_family == CPU_SUBTYPE_INTEL_FAMILY_MAX + 1)
		return(NULL);
	    lowest_model = INT_MAX;
	    lowest_index = -1;
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if(CPU_SUBTYPE_INTEL_FAMILY(fat_archs[i].cpusubtype &
			~CPU_SUBTYPE_MASK) == lowest_family){
		    if(CPU_SUBTYPE_INTEL_MODEL(fat_archs[i].cpusubtype &
			~CPU_SUBTYPE_MASK) < lowest_model){
		        lowest_model = CPU_SUBTYPE_INTEL_MODEL(
					fat_archs[i].cpusubtype &
					~CPU_SUBTYPE_MASK);
			lowest_index = i;
		    }
		}
	    }
	    return(fat_archs + lowest_index);
	case CPU_TYPE_X86_64:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_X86_64_ALL)
		    return(fat_archs + i);
	    }
	    break;
	case CPU_TYPE_MC680x0:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_MC680x0_ALL)
		    return(fat_archs + i);
	    }
	    /*
	     * Try to promote if starting from CPU_SUBTYPE_MC680x0_ALL and
	     * favor the CPU_SUBTYPE_MC68040 over the CPU_SUBTYPE_MC68030_ONLY.
	     */
	    if((cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_MC680x0_ALL){
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_MC68040)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		       CPU_SUBTYPE_MC68030_ONLY)
			return(fat_archs + i);
		}
	    }
	    break;
	case CPU_TYPE_POWERPC:
	    /*
	     * An exact match as not found.  So for all the PowerPC subtypes
	     * pick the subtype from the following order starting from a subtype
	     * that will work (contains 64-bit instructions or altivec if
	     * needed):
	     *	970, 7450, 7400, 750, 604e, 604, 603ev, 603e, 603, ALL
	     * Note the 601 is NOT in the list above.  It is only picked via
	     * an exact match.  For an unknown subtype pick only the ALL type if
	     * it exists.
	     */
	    switch(cpusubtype & ~CPU_SUBTYPE_MASK){
	    case CPU_SUBTYPE_POWERPC_ALL:
		/*
		 * The CPU_SUBTYPE_POWERPC_ALL is only used by the development
		 * environment tools when building a generic ALL type binary.
		 * In the case of a non-exact match we pick the most current
		 * processor.
		 */
	    case CPU_SUBTYPE_POWERPC_970:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_POWERPC_970)
			return(fat_archs + i);
		}
	    case CPU_SUBTYPE_POWERPC_7450:
	    case CPU_SUBTYPE_POWERPC_7400:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_POWERPC_7450)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_POWERPC_7400)
			return(fat_archs + i);
		}
	    case CPU_SUBTYPE_POWERPC_750:
	    case CPU_SUBTYPE_POWERPC_604e:
	    case CPU_SUBTYPE_POWERPC_604:
	    case CPU_SUBTYPE_POWERPC_603ev:
	    case CPU_SUBTYPE_POWERPC_603e:
	    case CPU_SUBTYPE_POWERPC_603:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_POWERPC_750)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_POWERPC_604e)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_POWERPC_604)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if((fat_archs[i].cputype & ~CPU_SUBTYPE_MASK) != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_POWERPC_603ev)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_POWERPC_603e)
			return(fat_archs + i);
		}
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_POWERPC_603)
			return(fat_archs + i);
		}
	    default:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_POWERPC_ALL)
			return(fat_archs + i);
		}
	    }
	    break;
	case CPU_TYPE_POWERPC64:
	    /*
	     * An exact match as not found.  So for all the PowerPC64 subtypes
	     * pick the subtype from the following order starting from a subtype
	     * that will work (contains 64-bit instructions or altivec if
	     * needed):
	     *	970 (currently only the one 64-bit subtype)
	     * For an unknown subtype pick only the ALL type if it exists.
	     */
	    switch(cpusubtype & ~CPU_SUBTYPE_MASK){
	    case CPU_SUBTYPE_POWERPC_ALL:
		/*
		 * The CPU_SUBTYPE_POWERPC_ALL is only used by the development
		 * environment tools when building a generic ALL type binary.
		 * In the case of a non-exact match we pick the most current
		 * processor.
		 */
	    case CPU_SUBTYPE_POWERPC_970:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_POWERPC_970)
			return(fat_archs + i);
		}
	    default:
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
			CPU_SUBTYPE_POWERPC_ALL)
			return(fat_archs + i);
		}
	    }
	    break;
	case CPU_TYPE_MC88000:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_MC88000_ALL)
		    return(fat_archs + i);
	    }
	    break;
	case CPU_TYPE_I860:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_I860_ALL)
		    return(fat_archs + i);
	    }
	    break;
	case CPU_TYPE_HPPA:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_HPPA_ALL)
		    return(fat_archs + i);
	    }
	    break;
	case CPU_TYPE_SPARC:
	    for(i = 0; i < nfat_archs; i++){
		if(fat_archs[i].cputype != cputype)
		    continue;
		if((fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
		   CPU_SUBTYPE_SPARC_ALL)
		    return(fat_archs + i);
	    }
	    break;
	case CPU_TYPE_ARM:
	    {
		/* 
		 * ARM is straightforward, since each architecture is backward
		 * compatible with previous architectures.  So, we just take the
		 * highest that is less than our target.
		 */
		int fat_match_found = 0;
		uint32_t best_fat_arch = 0;
		for(i = 0; i < nfat_archs; i++){
		    if(fat_archs[i].cputype != cputype)
			continue;
		    if(fat_archs[i].cpusubtype > cpusubtype)
			continue;
		    if(!fat_match_found){
			fat_match_found = 1;
			best_fat_arch = i;
			continue;
		    }
		    if(fat_archs[i].cpusubtype >
		       fat_archs[best_fat_arch].cpusubtype)
			best_fat_arch = i;
		}
		if(fat_match_found)
		  return fat_archs + best_fat_arch;
	    }
	    break;
	default:
	    return(NULL);
	}
	return(NULL);
}