Make sure a 32-bit B2/JIT works reasonnably well on AMD64 too. This implies

to force RAMBaseHost < 0x80000000. This is empirically determined to work on
Linux/x86 and Linux/amd64.
This commit is contained in:
gbeauche 2003-10-03 18:18:15 +00:00
parent 87e4d48b3e
commit b66f5972f9
2 changed files with 80 additions and 5 deletions

View File

@ -38,20 +38,38 @@
#endif
#endif
/* We want MAP_32BIT, if available, for SheepShaver and BasiliskII
because the emulated target is 32-bit and this helps to allocate
memory so that branches could be resolved more easily (32-bit
displacement to code in .text), on AMD64 for example. */
#ifndef MAP_32BIT
#define MAP_32BIT 0
#endif
#define MAP_EXTRA_FLAGS (MAP_32BIT)
#ifdef HAVE_MMAP_VM
static char * next_address = 0;
#if defined(__linux__) && defined(__i386__)
/* Force a reasonnable address below 0x80000000 on x86 so that we
don't get addresses above when the program is run on AMD64.
NOTE: this is empirically determined on Linux/x86. */
#define MAP_BASE 0x10000000
#else
#define MAP_BASE 0x00000000
#endif
static char * next_address = (char *)MAP_BASE;
#ifdef HAVE_MMAP_ANON
#define map_flags (MAP_PRIVATE | MAP_ANON)
#define map_flags (MAP_PRIVATE | MAP_ANON | MAP_EXTRA_FLAGS)
#define zero_fd -1
#else
#ifdef HAVE_MMAP_ANONYMOUS
#define map_flags (MAP_PRIVATE | MAP_ANONYMOUS)
#define map_flags (MAP_PRIVATE | MAP_ANONYMOUS | MAP_EXTRA_FLAGS)
#define zero_fd -1
#else
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#define map_flags (MAP_PRIVATE)
#define map_flags (MAP_PRIVATE | MAP_EXTRA_FLAGS)
static int zero_fd = -1;
#endif
#endif

View File

@ -37,6 +37,7 @@
#define USE_NORMAL_CALLING_CONVENTION 0
#ifndef WIN32
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#endif
@ -5530,6 +5531,62 @@ uae_u32 get_jitted_size(void)
return 0;
}
const int CODE_ALLOC_MAX_ATTEMPTS = 10;
const int CODE_ALLOC_BOUNDARIES = 128 * 1024; // 128 KB
static uint8 *do_alloc_code(uint32 size, int depth)
{
#if defined(__linux__) && 0
/*
This is a really awful hack that is known to work on Linux at
least.
The trick here is to make sure the allocated cache is nearby
code segment, and more precisely in the positive half of a
32-bit address space. i.e. addr < 0x80000000. Actually, it
turned out that a 32-bit binary run on AMD64 yields a cache
allocated around 0xa0000000, thus causing some troubles when
translating addresses from m68k to x86.
*/
static uint8 * code_base = NULL;
if (code_base == NULL) {
uintptr page_size = getpagesize();
uintptr boundaries = CODE_ALLOC_BOUNDARIES;
if (boundaries < page_size)
boundaries = page_size;
code_base = (uint8 *)sbrk(0);
for (int attempts = 0; attempts < CODE_ALLOC_MAX_ATTEMPTS; attempts++) {
if (vm_acquire_fixed(code_base, size) == 0) {
uint8 *code = code_base;
code_base += size;
return code;
}
code_base += boundaries;
}
return NULL;
}
if (vm_acquire_fixed(code_base, size) == 0) {
uint8 *code = code_base;
code_base += size;
return code;
}
if (depth >= CODE_ALLOC_MAX_ATTEMPTS)
return NULL;
return do_alloc_code(size, depth + 1);
#else
uint8 *code = (uint8 *)vm_acquire(size);
return code == VM_MAP_FAILED ? NULL : code;
#endif
}
static inline uint8 *alloc_code(uint32 size)
{
return do_alloc_code(size, 0);
}
void alloc_cache(void)
{
if (compiled_code) {
@ -5542,7 +5599,7 @@ void alloc_cache(void)
return;
while (!compiled_code && cache_size) {
if ((compiled_code = (uae_u8 *)vm_acquire(cache_size * 1024)) == VM_MAP_FAILED) {
if ((compiled_code = alloc_code(cache_size * 1024)) == NULL) {
compiled_code = 0;
cache_size /= 2;
}