343 lines
10 KiB
C
343 lines
10 KiB
C
/*
|
|
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
|
|
*
|
|
* @APPLE_LICENSE_HEADER_START@
|
|
*
|
|
* This file contains Original Code and/or Modifications of Original Code
|
|
* as defined in and that are subject to the Apple Public Source License
|
|
* Version 2.0 (the 'License'). You may not use this file except in
|
|
* compliance with the License. Please obtain a copy of the License at
|
|
* http://www.opensource.apple.com/apsl/ and read it before using this
|
|
* file.
|
|
*
|
|
* The Original Code and all software distributed under the License are
|
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
|
* Please see the License for the specific language governing rights and
|
|
* limitations under the License.
|
|
*
|
|
* @APPLE_LICENSE_HEADER_END@
|
|
*/
|
|
#ifndef RLD
|
|
#include "stdio.h"
|
|
#endif /* !defined(RLD) */
|
|
#include "stdlib.h"
|
|
#include "string.h"
|
|
#include <mach/mach.h>
|
|
#include "stuff/openstep_mach.h"
|
|
#include "stuff/arch.h"
|
|
#include "stuff/allocate.h"
|
|
|
|
/*
|
|
* The array of all currently know architecture flags (terminated with an entry
|
|
* with all zeros). Pointer to this returned with get_arch_flags().
|
|
*/
|
|
#ifdef __DYNAMIC__
|
|
static struct arch_flag arch_flags[] = {
|
|
#else
|
|
static const struct arch_flag arch_flags[] = {
|
|
#endif
|
|
{ "any", CPU_TYPE_ANY, CPU_SUBTYPE_MULTIPLE },
|
|
{ "little", CPU_TYPE_ANY, CPU_SUBTYPE_LITTLE_ENDIAN },
|
|
{ "big", CPU_TYPE_ANY, CPU_SUBTYPE_BIG_ENDIAN },
|
|
|
|
/* 64-bit Mach-O architectures */
|
|
|
|
/* architecture families */
|
|
{ "ppc64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_ALL },
|
|
{ "x86_64", CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL },
|
|
/* specific architecture implementations */
|
|
{ "ppc970-64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_970 },
|
|
|
|
/* 32-bit Mach-O architectures */
|
|
|
|
/* architecture families */
|
|
{ "ppc", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL },
|
|
{ "i386", CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL },
|
|
{ "m68k", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC680x0_ALL },
|
|
{ "hppa", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_ALL },
|
|
{ "sparc", CPU_TYPE_SPARC, CPU_SUBTYPE_SPARC_ALL },
|
|
{ "m88k", CPU_TYPE_MC88000, CPU_SUBTYPE_MC88000_ALL },
|
|
{ "i860", CPU_TYPE_I860, CPU_SUBTYPE_I860_ALL },
|
|
{ "veo", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_ALL },
|
|
/* specific architecture implementations */
|
|
{ "ppc601", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_601 },
|
|
{ "ppc603", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603 },
|
|
{ "ppc603e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603e },
|
|
{ "ppc603ev",CPU_TYPE_POWERPC,CPU_SUBTYPE_POWERPC_603ev },
|
|
{ "ppc604", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604 },
|
|
{ "ppc604e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604e },
|
|
{ "ppc750", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_750 },
|
|
{ "ppc7400",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7400 },
|
|
{ "ppc7450",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7450 },
|
|
{ "ppc970", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_970 },
|
|
{ "i486", CPU_TYPE_I386, CPU_SUBTYPE_486 },
|
|
{ "i486SX", CPU_TYPE_I386, CPU_SUBTYPE_486SX },
|
|
{ "pentium",CPU_TYPE_I386, CPU_SUBTYPE_PENT }, /* same as i586 */
|
|
{ "i586", CPU_TYPE_I386, CPU_SUBTYPE_586 },
|
|
{ "pentpro", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO }, /* same as i686 */
|
|
{ "i686", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO },
|
|
{ "pentIIm3",CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M3 },
|
|
{ "pentIIm5",CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M5 },
|
|
{ "pentium4",CPU_TYPE_I386, CPU_SUBTYPE_PENTIUM_4 },
|
|
{ "m68030", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68030_ONLY },
|
|
{ "m68040", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68040 },
|
|
{ "hppa7100LC", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_7100LC },
|
|
{ "veo1", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_1 },
|
|
{ "veo2", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_2 },
|
|
{ "veo3", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_3 },
|
|
{ "veo4", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_4 },
|
|
{ NULL, 0, 0 }
|
|
};
|
|
|
|
#ifndef RLD
|
|
/*
|
|
* get_arch_from_flag() is passed a name of an architecture flag and returns
|
|
* zero if that flag is not known and non-zero if the flag is known.
|
|
* If the pointer to the arch_flag is not NULL it is filled in with the
|
|
* arch_flag struct that matches the name.
|
|
*/
|
|
__private_extern__
|
|
int
|
|
get_arch_from_flag(
|
|
char *name,
|
|
struct arch_flag *arch_flag)
|
|
{
|
|
unsigned long i;
|
|
|
|
for(i = 0; arch_flags[i].name != NULL; i++){
|
|
if(strcmp(arch_flags[i].name, name) == 0){
|
|
if(arch_flag != NULL)
|
|
*arch_flag = arch_flags[i];
|
|
return(1);
|
|
}
|
|
}
|
|
if(arch_flag != NULL)
|
|
memset(arch_flag, '\0', sizeof(struct arch_flag));
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* get_arch_flags() returns a pointer to an array of all currently know
|
|
* architecture flags (terminated with an entry with all zeros).
|
|
*/
|
|
__private_extern__
|
|
const struct arch_flag *
|
|
get_arch_flags(
|
|
void)
|
|
{
|
|
return(arch_flags);
|
|
}
|
|
#endif /* !defined(RLD) */
|
|
|
|
/*
|
|
* get_arch_name_from_types() returns the name of the architecture for the
|
|
* specified cputype and cpusubtype if known. If unknown it returns a pointer
|
|
* to the an allocated string "cputype X cpusubtype Y" where X and Y are decimal
|
|
* values.
|
|
*/
|
|
__private_extern__
|
|
const char *
|
|
get_arch_name_from_types(
|
|
cpu_type_t cputype,
|
|
cpu_subtype_t cpusubtype)
|
|
{
|
|
unsigned long i;
|
|
char *p;
|
|
|
|
for(i = 0; arch_flags[i].name != NULL; i++){
|
|
if(arch_flags[i].cputype == cputype &&
|
|
(arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
|
|
(cpusubtype & ~CPU_SUBTYPE_MASK))
|
|
return(arch_flags[i].name);
|
|
}
|
|
#ifndef RLD
|
|
p = savestr("cputype 1234567890 cpusubtype 1234567890");
|
|
if(p != NULL)
|
|
sprintf(p, "cputype %u cpusubtype %u", cputype,
|
|
cpusubtype & ~CPU_SUBTYPE_MASK);
|
|
#else
|
|
/* there is no sprintf() in the rld kernel API's */
|
|
p = savestr("cputype ?? cpusubtype ??");
|
|
#endif
|
|
return(p);
|
|
}
|
|
|
|
/*
|
|
* get_arch_family_from_cputype() returns the family architecture for the
|
|
* specified cputype if known. If unknown it returns NULL.
|
|
*/
|
|
__private_extern__
|
|
const struct arch_flag *
|
|
get_arch_family_from_cputype(
|
|
cpu_type_t cputype)
|
|
{
|
|
unsigned long i;
|
|
|
|
for(i = 0; arch_flags[i].name != NULL; i++){
|
|
if(arch_flags[i].cputype == cputype)
|
|
return(arch_flags + i);
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
/*
|
|
* get_byte_sex_from_flag() returns the byte sex of the architecture for the
|
|
* specified cputype and cpusubtype if known. If unknown it returns
|
|
* UNKNOWN_BYTE_SEX. If the bytesex can be determined directly as in the case
|
|
* of reading a magic number from a file that should be done and this routine
|
|
* should not be used as it could be out of date.
|
|
*/
|
|
__private_extern__
|
|
enum byte_sex
|
|
get_byte_sex_from_flag(
|
|
const struct arch_flag *flag)
|
|
{
|
|
if(flag->cputype == CPU_TYPE_MC680x0 ||
|
|
flag->cputype == CPU_TYPE_MC88000 ||
|
|
flag->cputype == CPU_TYPE_POWERPC ||
|
|
flag->cputype == CPU_TYPE_POWERPC64 ||
|
|
flag->cputype == CPU_TYPE_HPPA ||
|
|
flag->cputype == CPU_TYPE_SPARC ||
|
|
flag->cputype == CPU_TYPE_I860 ||
|
|
flag->cputype == CPU_TYPE_VEO)
|
|
return BIG_ENDIAN_BYTE_SEX;
|
|
else if(flag->cputype == CPU_TYPE_I386)
|
|
return LITTLE_ENDIAN_BYTE_SEX;
|
|
else
|
|
return UNKNOWN_BYTE_SEX;
|
|
}
|
|
|
|
#ifndef RLD
|
|
/*
|
|
* get_stack_direction_from_flag() returns the direction the stack grows as
|
|
* either positive (+1) or negative (-1) of the architecture for the
|
|
* specified cputype and cpusubtype if known. If unknown it returns 0.
|
|
*/
|
|
__private_extern__
|
|
long
|
|
get_stack_direction_from_flag(
|
|
const struct arch_flag *flag)
|
|
{
|
|
if(flag->cputype == CPU_TYPE_MC680x0 ||
|
|
flag->cputype == CPU_TYPE_MC88000 ||
|
|
flag->cputype == CPU_TYPE_POWERPC ||
|
|
flag->cputype == CPU_TYPE_I386 ||
|
|
flag->cputype == CPU_TYPE_SPARC ||
|
|
flag->cputype == CPU_TYPE_I860 ||
|
|
flag->cputype == CPU_TYPE_VEO)
|
|
return(-1);
|
|
else if(flag->cputype == CPU_TYPE_HPPA)
|
|
return(+1);
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* get_stack_addr_from_flag() returns the default starting address of the user
|
|
* stack. This should be in the header file <bsd/XXX/vmparam.h> as USRSTACK.
|
|
* Since some architectures have come and gone and come back and because you
|
|
* can't include all of these headers in one source the constants have been
|
|
* copied here.
|
|
*/
|
|
__private_extern__
|
|
uint64_t
|
|
get_stack_addr_from_flag(
|
|
const struct arch_flag *flag)
|
|
{
|
|
switch(flag->cputype){
|
|
case CPU_TYPE_MC680x0:
|
|
return(0x04000000);
|
|
case CPU_TYPE_MC88000:
|
|
return(0xffffe000);
|
|
case CPU_TYPE_POWERPC:
|
|
case CPU_TYPE_VEO:
|
|
return(0xc0000000);
|
|
case CPU_TYPE_I386:
|
|
return(0xc0000000);
|
|
case CPU_TYPE_SPARC:
|
|
return(0xf0000000);
|
|
case CPU_TYPE_I860:
|
|
return(0);
|
|
case CPU_TYPE_HPPA:
|
|
return(0xc0000000-0x04000000);
|
|
case CPU_TYPE_POWERPC64:
|
|
return(0x7ffff00000000LL);
|
|
case CPU_TYPE_X86_64:
|
|
return(0x7fff5fc00000LL);
|
|
default:
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* get_stack_size_from_flag() returns the default size of the userstack. This
|
|
* should be in the header file <bsd/XXX/vmparam.h> as MAXSSIZ. Since some
|
|
* architectures have come and gone and come back, you can't include all of
|
|
* these headers in one source and some of the constants covered the whole
|
|
* address space the common value of 64meg was chosen.
|
|
*/
|
|
__private_extern__
|
|
unsigned long
|
|
get_stack_size_from_flag(
|
|
const struct arch_flag *flag)
|
|
{
|
|
#ifdef __MWERKS__
|
|
const struct arch_flag *dummy;
|
|
dummy = flag;
|
|
#endif
|
|
|
|
return(64*1024*1024);
|
|
}
|
|
#endif /* !defined(RLD) */
|
|
|
|
/*
|
|
* get_segalign_from_flag() returns the default segment alignment (page size).
|
|
*/
|
|
__private_extern__
|
|
unsigned long
|
|
get_segalign_from_flag(
|
|
const struct arch_flag *flag)
|
|
{
|
|
if(flag->cputype == CPU_TYPE_POWERPC ||
|
|
flag->cputype == CPU_TYPE_POWERPC64 ||
|
|
flag->cputype == CPU_TYPE_VEO ||
|
|
flag->cputype == CPU_TYPE_I386 ||
|
|
flag->cputype == CPU_TYPE_X86_64)
|
|
return(0x1000); /* 4K */
|
|
else
|
|
return(0x2000); /* 8K */
|
|
}
|
|
|
|
/*
|
|
* get_segprot_from_flag() returns the default segment protection.
|
|
*/
|
|
__private_extern__
|
|
vm_prot_t
|
|
get_segprot_from_flag(
|
|
const struct arch_flag *flag)
|
|
{
|
|
if(flag->cputype == CPU_TYPE_I386)
|
|
return(VM_PROT_READ | VM_PROT_WRITE);
|
|
else
|
|
return(VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
|
|
}
|
|
|
|
/*
|
|
* force_cpusubtype_ALL_for_cputype() takes a cputype and returns TRUE if for
|
|
* that cputype the cpusubtype should always be forced to the ALL cpusubtype,
|
|
* otherwise it returns FALSE.
|
|
*/
|
|
__private_extern__
|
|
enum bool
|
|
force_cpusubtype_ALL_for_cputype(
|
|
cpu_type_t cputype)
|
|
{
|
|
if(cputype == CPU_TYPE_I386)
|
|
return(TRUE);
|
|
else
|
|
return(FALSE);
|
|
}
|