/* * 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); }
/* * 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); }
/* * 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); }
/* * 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 */ }
/* * 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); }
uint extractCpuSubtypeIntelModel(uint x){ return CPU_SUBTYPE_INTEL_MODEL(x); }
/* * 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); }