ld64 with ppc
[darwin-xtools.git] / cctools / libstuff / arch.c
blobe43c2401e775b9adf388b0a665fff0a290f939c6
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 #ifndef RLD
24 #include "stdio.h"
25 #endif /* !defined(RLD) */
26 #include "stdlib.h"
27 #include "string.h"
28 #include <mach/mach.h>
29 #include "stuff/openstep_mach.h"
30 #include "stuff/arch.h"
31 #include "stuff/allocate.h"
34 * The array of all currently know architecture flags (terminated with an entry
35 * with all zeros). Pointer to this returned with get_arch_flags().
37 #ifdef __DYNAMIC__
38 static struct arch_flag arch_flags[] = {
39 #else
40 static const struct arch_flag arch_flags[] = {
41 #endif
42 { "any", CPU_TYPE_ANY, CPU_SUBTYPE_MULTIPLE },
43 { "little", CPU_TYPE_ANY, CPU_SUBTYPE_LITTLE_ENDIAN },
44 { "big", CPU_TYPE_ANY, CPU_SUBTYPE_BIG_ENDIAN },
46 /* 64-bit Mach-O architectures */
48 /* architecture families */
49 { "ppc64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_ALL },
50 { "x86_64", CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL },
51 { "x86_64h", CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_H },
52 { "arm64", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL },
53 /* specific architecture implementations */
54 { "ppc970-64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_970 },
56 /* 32-bit Mach-O architectures */
58 /* architecture families */
59 { "ppc", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL },
60 { "i386", CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL },
61 { "m68k", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC680x0_ALL },
62 { "hppa", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_ALL },
63 { "sparc", CPU_TYPE_SPARC, CPU_SUBTYPE_SPARC_ALL },
64 { "m88k", CPU_TYPE_MC88000, CPU_SUBTYPE_MC88000_ALL },
65 { "i860", CPU_TYPE_I860, CPU_SUBTYPE_I860_ALL },
66 { "veo", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_ALL },
67 { "arm", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_ALL },
68 /* specific architecture implementations */
69 { "ppc601", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_601 },
70 { "ppc603", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603 },
71 { "ppc603e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603e },
72 { "ppc603ev",CPU_TYPE_POWERPC,CPU_SUBTYPE_POWERPC_603ev },
73 { "ppc604", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604 },
74 { "ppc604e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604e },
75 { "ppc750", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_750 },
76 { "ppc7400",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7400 },
77 { "ppc7450",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7450 },
78 { "ppc970", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_970 },
79 { "i486", CPU_TYPE_I386, CPU_SUBTYPE_486 },
80 { "i486SX", CPU_TYPE_I386, CPU_SUBTYPE_486SX },
81 { "pentium",CPU_TYPE_I386, CPU_SUBTYPE_PENT }, /* same as i586 */
82 { "i586", CPU_TYPE_I386, CPU_SUBTYPE_586 },
83 { "pentpro", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO }, /* same as i686 */
84 { "i686", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO },
85 { "pentIIm3",CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M3 },
86 { "pentIIm5",CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M5 },
87 { "pentium4",CPU_TYPE_I386, CPU_SUBTYPE_PENTIUM_4 },
88 { "m68030", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68030_ONLY },
89 { "m68040", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68040 },
90 { "hppa7100LC", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_7100LC },
91 { "veo1", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_1 },
92 { "veo2", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_2 },
93 { "veo3", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_3 },
94 { "veo4", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_4 },
95 { "armv4t", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V4T},
96 { "armv5", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V5TEJ},
97 { "xscale", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_XSCALE},
98 { "armv6", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6 },
99 { "armv6m", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6M },
100 { "armv7", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7 },
101 { "armv7f", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7F },
102 { "armv7s", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S },
103 { "armv7k", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7K },
104 { "armv7m", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7M },
105 { "armv7em", CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7EM },
106 { "arm64v8",CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_V8 },
107 { NULL, 0, 0 }
110 #ifndef RLD
112 * get_arch_from_flag() is passed a name of an architecture flag and returns
113 * zero if that flag is not known and non-zero if the flag is known.
114 * If the pointer to the arch_flag is not NULL it is filled in with the
115 * arch_flag struct that matches the name.
117 __private_extern__
119 get_arch_from_flag(
120 char *name,
121 struct arch_flag *arch_flag)
123 uint32_t i;
125 for(i = 0; arch_flags[i].name != NULL; i++){
126 if(strcmp(arch_flags[i].name, name) == 0){
127 if(arch_flag != NULL)
128 *arch_flag = arch_flags[i];
129 return(1);
132 if(arch_flag != NULL)
133 memset(arch_flag, '\0', sizeof(struct arch_flag));
134 return(0);
138 * get_arch_flags() returns a pointer to an array of all currently know
139 * architecture flags (terminated with an entry with all zeros).
141 __private_extern__
142 const struct arch_flag *
143 get_arch_flags(
144 void)
146 return(arch_flags);
148 #endif /* !defined(RLD) */
151 * get_arch_name_from_types() returns the name of the architecture for the
152 * specified cputype and cpusubtype if known. If unknown it returns a pointer
153 * to the an allocated string "cputype X cpusubtype Y" where X and Y are decimal
154 * values.
156 __private_extern__
157 const char *
158 get_arch_name_from_types(
159 cpu_type_t cputype,
160 cpu_subtype_t cpusubtype)
162 uint32_t i;
163 char *p;
165 for(i = 0; arch_flags[i].name != NULL; i++){
166 if(arch_flags[i].cputype == cputype &&
167 (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
168 (cpusubtype & ~CPU_SUBTYPE_MASK))
169 return(arch_flags[i].name);
171 #ifndef RLD
172 p = savestr("cputype 1234567890 cpusubtype 1234567890");
173 if(p != NULL)
174 sprintf(p, "cputype %u cpusubtype %u", cputype,
175 cpusubtype & ~CPU_SUBTYPE_MASK);
176 #else
177 /* there is no sprintf() in the rld kernel API's */
178 p = savestr("cputype ?? cpusubtype ??");
179 #endif
180 return(p);
184 * get_arch_family_from_cputype() returns the family architecture for the
185 * specified cputype if known. If unknown it returns NULL.
187 __private_extern__
188 const struct arch_flag *
189 get_arch_family_from_cputype(
190 cpu_type_t cputype)
192 uint32_t i;
194 for(i = 0; arch_flags[i].name != NULL; i++){
195 if(arch_flags[i].cputype == cputype)
196 return(arch_flags + i);
198 return(NULL);
202 * get_byte_sex_from_flag() returns the byte sex of the architecture for the
203 * specified cputype and cpusubtype if known. If unknown it returns
204 * UNKNOWN_BYTE_SEX. If the bytesex can be determined directly as in the case
205 * of reading a magic number from a file that should be done and this routine
206 * should not be used as it could be out of date.
208 __private_extern__
209 enum byte_sex
210 get_byte_sex_from_flag(
211 const struct arch_flag *flag)
213 if(flag->cputype == CPU_TYPE_MC680x0 ||
214 flag->cputype == CPU_TYPE_MC88000 ||
215 flag->cputype == CPU_TYPE_POWERPC ||
216 flag->cputype == CPU_TYPE_POWERPC64 ||
217 flag->cputype == CPU_TYPE_HPPA ||
218 flag->cputype == CPU_TYPE_SPARC ||
219 flag->cputype == CPU_TYPE_I860 ||
220 flag->cputype == CPU_TYPE_VEO)
221 return BIG_ENDIAN_BYTE_SEX;
222 else if(flag->cputype == CPU_TYPE_I386 ||
223 flag->cputype == CPU_TYPE_X86_64 ||
224 flag->cputype == CPU_TYPE_ARM64 ||
225 flag->cputype == CPU_TYPE_ARM)
226 return LITTLE_ENDIAN_BYTE_SEX;
227 else
228 return UNKNOWN_BYTE_SEX;
231 #ifndef RLD
233 * get_stack_direction_from_flag() returns the direction the stack grows as
234 * either positive (+1) or negative (-1) of the architecture for the
235 * specified cputype and cpusubtype if known. If unknown it returns 0.
237 __private_extern__
239 get_stack_direction_from_flag(
240 const struct arch_flag *flag)
242 if(flag->cputype == CPU_TYPE_MC680x0 ||
243 flag->cputype == CPU_TYPE_MC88000 ||
244 flag->cputype == CPU_TYPE_POWERPC ||
245 flag->cputype == CPU_TYPE_I386 ||
246 flag->cputype == CPU_TYPE_SPARC ||
247 flag->cputype == CPU_TYPE_I860 ||
248 flag->cputype == CPU_TYPE_VEO ||
249 flag->cputype == CPU_TYPE_ARM)
250 return(-1);
251 else if(flag->cputype == CPU_TYPE_HPPA)
252 return(+1);
253 else
254 return(0);
258 * get_stack_addr_from_flag() returns the default starting address of the user
259 * stack. This should be in the header file <bsd/XXX/vmparam.h> as USRSTACK.
260 * Since some architectures have come and gone and come back and because you
261 * can't include all of these headers in one source the constants have been
262 * copied here.
264 __private_extern__
265 uint64_t
266 get_stack_addr_from_flag(
267 const struct arch_flag *flag)
269 switch(flag->cputype){
270 case CPU_TYPE_MC680x0:
271 return(0x04000000);
272 case CPU_TYPE_MC88000:
273 return(0xffffe000);
274 case CPU_TYPE_POWERPC:
275 case CPU_TYPE_VEO:
276 case CPU_TYPE_I386:
277 return(0xc0000000);
278 case CPU_TYPE_ARM:
279 return(0x30000000);
280 case CPU_TYPE_SPARC:
281 return(0xf0000000);
282 case CPU_TYPE_I860:
283 return(0);
284 case CPU_TYPE_HPPA:
285 return(0xc0000000-0x04000000);
286 case CPU_TYPE_POWERPC64:
287 return(0x7ffff00000000LL);
288 case CPU_TYPE_X86_64:
289 return(0x7fff5fc00000LL);
290 default:
291 return(0);
296 * get_stack_size_from_flag() returns the default size of the userstack. This
297 * should be in the header file <bsd/XXX/vmparam.h> as MAXSSIZ. Since some
298 * architectures have come and gone and come back, you can't include all of
299 * these headers in one source and some of the constants covered the whole
300 * address space the common value of 64meg was chosen.
302 __private_extern__
303 uint32_t
304 get_stack_size_from_flag(
305 const struct arch_flag *flag)
307 #ifdef __MWERKS__
308 const struct arch_flag *dummy;
309 dummy = flag;
310 #endif
312 return(64*1024*1024);
314 #endif /* !defined(RLD) */
317 * get_segalign_from_flag() returns the default segment alignment (page size).
319 __private_extern__
320 uint32_t
321 get_segalign_from_flag(
322 const struct arch_flag *flag)
324 if(flag->cputype == CPU_TYPE_ARM ||
325 flag->cputype == CPU_TYPE_ARM64)
326 return(0x4000); /* 16K */
328 if(flag->cputype == CPU_TYPE_POWERPC ||
329 flag->cputype == CPU_TYPE_POWERPC64 ||
330 flag->cputype == CPU_TYPE_VEO ||
331 flag->cputype == CPU_TYPE_I386 ||
332 flag->cputype == CPU_TYPE_X86_64)
333 return(0x1000); /* 4K */
334 else
335 return(0x2000); /* 8K */
339 * get_segprot_from_flag() returns the default segment protection.
341 __private_extern__
342 vm_prot_t
343 get_segprot_from_flag(
344 const struct arch_flag *flag)
346 if(flag->cputype == CPU_TYPE_I386)
347 return(VM_PROT_READ | VM_PROT_WRITE);
348 else
349 return(VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
353 * get_shared_region_size_from_flag() returns the default shared
354 * region size.
356 __private_extern__
357 uint32_t
358 get_shared_region_size_from_flag(
359 const struct arch_flag *flag)
361 if(flag->cputype == CPU_TYPE_ARM)
362 return (0x08000000);
363 else
364 return (0x10000000);
368 * force_cpusubtype_ALL_for_cputype() takes a cputype and returns TRUE if for
369 * that cputype the cpusubtype should always be forced to the ALL cpusubtype,
370 * otherwise it returns FALSE.
372 __private_extern__
373 enum bool
374 force_cpusubtype_ALL_for_cputype(
375 cpu_type_t cputype)
377 if(cputype == CPU_TYPE_I386)
378 return(TRUE);
379 else
380 return(FALSE);