diff --git a/SheepShaver/src/Unix/configure.ac b/SheepShaver/src/Unix/configure.ac index 68394751..cc0d05a0 100644 --- a/SheepShaver/src/Unix/configure.ac +++ b/SheepShaver/src/Unix/configure.ac @@ -1033,7 +1033,7 @@ fi AC_MSG_RESULT($HAVE_ICC) dnl Determine the generated object format -AC_CACHE_CHECK([whether the compiler can generate ELF objects], +AC_CACHE_CHECK([the format of compiler generated objects], ac_cv_object_format, [ echo 'int i;' > conftest.$ac_ext ac_cv_object_format=no @@ -1042,6 +1042,9 @@ AC_CACHE_CHECK([whether the compiler can generate ELF objects], *"ELF"*) ac_cv_object_format=elf ;; + *"Mach-O"*) + ac_cv_object_format=mach + ;; *) ac_cv_object_format=unknown ;; @@ -1074,6 +1077,9 @@ if [[ "x$EMULATED_PPC" = "xyes" ]]; then i?86:elf) ac_cv_use_dyngen=yes ;; + powerpc:mach) + ac_cv_use_dyngen=yes + ;; *:*) ac_cv_use_dyngen=no ;; @@ -1099,14 +1105,19 @@ if [[ "x$EMULATED_PPC" = "xyes" ]]; then case $host_cpu in i?86) DYNGEN_OP_FLAGS="-fomit-frame-pointer -mpreferred-stack-boundary=2" - if [[ "x$HAVE_GCC30" = "xyes" ]]; then - DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -falign-functions=0" - else - DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -malign-functions=0" + ;; + powerpc) + if [[ "x$ac_cv_object_format" = "xmach" ]]; then + DYNGEN_OP_FLAGS="-mdynamic-no-pic" fi ;; esac - DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -finline-limit=10000 -g0" + if [[ "x$HAVE_GCC30" = "xyes" ]]; then + DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -falign-functions=0" + else + DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -malign-functions=0" + fi + DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -finline-limit=10000 -fno-exceptions -g0" if [[ "x$HAVE_GCC30" = "xyes" ]]; then DYNGEN_OP_FLAGS="$DYNGEN_OP_FLAGS -fno-reorder-blocks -fno-optimize-sibling-calls" fi diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen-ops.cpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen-ops.cpp index 43c55f47..6ad5e007 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen-ops.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen-ops.cpp @@ -237,6 +237,9 @@ DEFINE_OP(8,T0,1,T1); #ifdef __powerpc__ #define FORCE_RET() asm volatile ("blr") #endif +#ifdef __ppc__ +#define FORCE_RET() asm volatile ("blr") +#endif #ifdef __s390__ #define FORCE_RET() asm volatile ("br %r14") #endif @@ -292,13 +295,17 @@ void OPPROTO op_execute(uint8 *entry_point, basic_cpu *this_cpu) #endif SLOW_DISPATCH(entry_point); func(); // NOTE: never called, fake to make compiler save return point +#ifdef ASM_OP_EXEC_RETURN_INSN + asm volatile ("1: .byte " ASM_OP_EXEC_RETURN_INSN); +#else asm volatile (ASM_DATA_SECTION); - asm volatile (".global " ASM_NAME(op_exec_return_offset)); + asm volatile (ASM_GLOBAL " " ASM_NAME(op_exec_return_offset)); asm volatile (ASM_NAME(op_exec_return_offset) ":"); asm volatile (".long 1f-" ASM_NAME(op_execute)); asm volatile (ASM_SIZE(op_exec_return_offset)); asm volatile (ASM_PREVIOUS_SECTION); asm volatile ("1:"); +#endif #ifdef REG_T3 reg_T3 = saved_T3; #endif diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp index 137ae59b..1bcd9ea1 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/jit/basic-dyngen.hpp @@ -28,7 +28,7 @@ // Set jump target address static inline void dg_set_jmp_target(uint8 *jmp_addr, uint8 *addr) { -#if defined(__powerpc__) +#if defined(__powerpc__) || defined(__ppc__) // patch the branch destination uint32 *ptr = (uint32 *)jmp_addr; uint32 val = *ptr; @@ -241,7 +241,7 @@ public: inline bool basic_dyngen::direct_jump_possible(uintptr target) const { -#if defined(__powerpc__) +#if defined(__powerpc__) || defined(__ppc__) const uintptr LI_OFFSET_MAX = 1 << 26; return (((target - (uintptr)code_ptr()) < LI_OFFSET_MAX) || (((uintptr)code_ptr() - target) < LI_OFFSET_MAX)); @@ -283,7 +283,7 @@ basic_dyngen::gen_exec_return() inline bool basic_dyngen::direct_call_possible(uintptr target) const { -#if defined(__powerpc__) +#if defined(__powerpc__) || defined(__ppc__) const uintptr LI_OFFSET_MAX = 1 << 26; return (((target - (uintptr)code_ptr()) < LI_OFFSET_MAX) || (((uintptr)code_ptr() - target) < LI_OFFSET_MAX)); diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen-exec.h b/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen-exec.h index 90c4c77c..c3648665 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen-exec.h +++ b/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen-exec.h @@ -85,7 +85,11 @@ extern int __op_param1 __hidden; extern int __op_param2 __hidden; extern int __op_param3 __hidden; #else +#if defined(__APPLE__) && defined(__MACH__) +static int __op_param1, __op_param2, __op_param3; +#else extern int __op_param1, __op_param2, __op_param3; +#endif #define PARAM1 ((long)(&__op_param1)) #define PARAM2 ((long)(&__op_param2)) #define PARAM3 ((long)(&__op_param3)) @@ -97,7 +101,7 @@ extern int __op_cpuparam; #endif // Direct block chaining support -#if defined(__powerpc__) +#if defined(__powerpc__) || defined(__ppc__) #define DYNGEN_FAST_DISPATCH(TARGET) asm volatile ("b " ASM_NAME(TARGET)) #endif #if defined(__i386__) || defined(__x86_64__) @@ -108,15 +112,26 @@ extern int __op_jmp0, __op_jmp1; // Sections handling #if defined(__CYGWIN__) || defined(_WIN32) -#define ASM_DATA_SECTION ".section .data\n" -#define ASM_PREVIOUS_SECTION ".section .text\n" -#define ASM_NAME(NAME) "_" #NAME -#define ASM_SIZE(NAME) "" +#define ASM_DATA_SECTION ".section .data\n" +#define ASM_PREVIOUS_SECTION ".section .text\n" +#define ASM_GLOBAL ".global" +#define ASM_NAME(NAME) "_" #NAME +#define ASM_SIZE "" +#elif defined(__APPLE__) && defined(__MACH__) +#define ASM_DATA_SECTION ".data\n" +#define ASM_PREVIOUS_SECTION ".text\n" +#define ASM_GLOBAL ".globl" +#define ASM_NAME(NAME) "_" #NAME +#define ASM_SIZE "" +#if defined(__ppc__) +#define ASM_OP_EXEC_RETURN_INSN "0x18,0xde,0xad,0xff" +#endif #else -#define ASM_DATA_SECTION ".section \".data\"\n" -#define ASM_PREVIOUS_SECTION ".previous\n" -#define ASM_NAME(NAME) #NAME -#define ASM_SIZE(NAME) ".size " ASM_NAME(NAME) ",.-" ASM_NAME(NAME) +#define ASM_DATA_SECTION ".section \".data\"\n" +#define ASM_PREVIOUS_SECTION ".previous\n" +#define ASM_GLOBAL ".global" +#define ASM_NAME(NAME) #NAME +#define ASM_SIZE(NAME) ".size " ASM_NAME(NAME) ",.-" ASM_NAME(NAME) #endif #endif /* DYNGEN_EXEC_H */ diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen.c b/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen.c index b617e648..481dfc34 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen.c +++ b/SheepShaver/src/kpx_cpu/src/cpu/jit/dyngen.c @@ -39,13 +39,18 @@ #define CONFIG_WIN32 1 #endif #endif +#ifndef CONFIG_DARWIN +#if defined(__APPLE__) && defined(__MACH__) +#define CONFIG_DARWIN 1 +#endif +#endif /* host cpu defs */ #if CONFIG_WIN32 #define HOST_I386 1 #elif defined(__i386__) #define HOST_I386 1 -#elif defined(__powerpc__) +#elif defined(__powerpc__) || defined(__ppc__) #define HOST_PPC 1 #elif defined(__s390__) #define HOST_S390 1 @@ -1083,6 +1088,7 @@ struct symtab_command *symtabcmd = 0; /* section */ struct section *section_hdr; struct section *text_sec_hdr; +struct section *data_sec_hdr; uint8_t **sdata; /* relocs */ @@ -1265,11 +1271,11 @@ static const char * get_reloc_name(EXE_RELOC * rel, int * sslide) switch(rel->r_type) { - case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset & 0xffff); + case PPC_RELOC_LO16: fetch_next_pair_value(rel+1, &other_half); sectoffset |= (other_half << 16); break; - case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (other_half & 0xffff); + case PPC_RELOC_HI16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) | (uint16_t)(other_half & 0xffff); break; - case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (other_half & 0xffff); + case PPC_RELOC_HA16: fetch_next_pair_value(rel+1, &other_half); sectoffset = (sectoffset << 16) + (int16_t)(other_half & 0xffff); break; case PPC_RELOC_BR24: sectoffset = ( *(uint32_t *)(text + rel->r_address) & 0x03fffffc ); @@ -1384,10 +1390,16 @@ int load_object(const char *filename, FILE *outfile) sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects); memset(sdata, 0, sizeof(void *) * segment->nsects); - /* Load the data in section data */ - for(i = 0; i < segment->nsects; i++) { + /* Load the data in section data */ + for(i = 0; i < segment->nsects; i++) sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size); - } + + /* data section */ + data_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_DATA, SECT_DATA); + i = find_mach_sec_index(section_hdr, segment->nsects, SEG_DATA, SECT_DATA); + if (i == -1 || !data_sec_hdr) + error("could not find __DATA,__data section"); + data = sdata[i]; /* text section */ text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT); @@ -1415,13 +1427,11 @@ int load_object(const char *filename, FILE *outfile) /* Now transform the symtab, to an extended version, with the sym size, and the C name */ for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) { - const char *name; struct nlist *sym_follow, *sym_next = 0; unsigned int j; - name = find_str_by_index(sym->n_un.n_strx); memset(sym, 0, sizeof(*sym)); - if ( sym->n_type & N_STAB ) /* Debug symbols are skipped */ + if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */ continue; memcpy(sym, syment, sizeof(*syment)); @@ -1581,8 +1591,16 @@ void gen_code(const char *name, const char *demangled_name, p_start = text + offset; p_end = p_start + size; start_offset = offset; - if (op_execute) - copy_size = p_end - p_start; + if (op_execute) { + uint8_t *p; + copy_size = p_end - p_start; +#if defined(HOST_PPC) + for (p = p_start; p < p_end; p += 4) { + if (get32((uint32_t *)p) == 0x18deadff) + fprintf(outfile, "DEFINE_CST(op_exec_return_offset,0x%xL)\n\n", (p + 4) - p_start); + } +#endif + } else #if defined(HOST_I386) || defined(HOST_AMD64) #ifdef CONFIG_FORMAT_COFF @@ -2130,11 +2148,16 @@ void gen_code(const char *name, const char *demangled_name, switch(type) { case PPC_RELOC_BR24: + if (!strstart(sym_name, "__op_param", &p)) { fprintf(outfile, "{\n"); fprintf(outfile, " uint32_t imm = *(uint32_t *)(code_ptr() + %d) & 0x3fffffc;\n", slide); fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = (*(uint32_t *)(code_ptr() + %d) & ~0x03fffffc) | ((imm + ((long)%s - (long)code_ptr()) + %d) & 0x03fffffc);\n", slide, slide, name, sslide ); fprintf(outfile, "}\n"); + } else { + fprintf(outfile, " *(uint32_t *)(code_ptr() + %d) = (*(uint32_t *)(code_ptr() + %d) & ~0x03fffffc) | (((long)%s - (long)code_ptr() - %d) & 0x03fffffc);\n", + slide, slide, final_sym_name, slide); + } break; case PPC_RELOC_HI16: fprintf(outfile, " *(uint16_t *)(code_ptr() + %d + 2) = (%s + %d) >> 16;\n", diff --git a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp b/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp index 7c5be256..476d7bee 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/jit/jit-cache.cpp @@ -32,7 +32,7 @@ // Default cache size #if defined(__alpha__) const int JIT_CACHE_SIZE = 2 * 1024 * 1024; -#elif defined(__powerpc__) +#elif defined(__powerpc__) || defined(__ppc__) const int JIT_CACHE_SIZE = 4 * 1024 * 1024; #else const int JIT_CACHE_SIZE = 8 * 1024 * 1024; diff --git a/SheepShaver/src/kpx_cpu/src/cpu/vm.hpp b/SheepShaver/src/kpx_cpu/src/cpu/vm.hpp index 9f19b800..ad5bff68 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/vm.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/vm.hpp @@ -25,7 +25,7 @@ /// Optimized memory accessors /// -#if defined(__i386__) || defined(__powerpc__) || defined(__m68k__) || defined(__x86_64__) +#if defined(__i386__) || defined(__powerpc__) || defined(__ppc__) || defined(__m68k__) || defined(__x86_64__) # define VM_CAN_ACCESS_UNALIGNED #endif