Hope it works

This commit is contained in:
uyjulian 2018-06-06 23:11:08 -05:00
parent 77e20bda2a
commit 8353a9ed44
No known key found for this signature in database
GPG Key ID: FEA459A8CA14685B
7 changed files with 124 additions and 308 deletions

View File

@ -104,6 +104,8 @@ set_source_files_properties(${BasiliskII_SRCS}
target_link_libraries(BasiliskII ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${SDL_LIBRARY})
# set(CMAKE_POSITION_INDEPENDENT_CODE OFF)
SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pagezero_size 0x2000" )
add_definitions(-march=native)

View File

@ -83,27 +83,17 @@ bool TwentyFourBitAddressing;
static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes
#ifdef HAVE_PTHREADS
static bool xpram_thread_active = false; // Flag: XPRAM watchdog installed
static volatile bool xpram_thread_cancel = false; // Flag: Cancel XPRAM thread
static pthread_t xpram_thread; // XPRAM watchdog
static SDL_Thread *xpram_thread = NULL; // XPRAM watchdog
static bool tick_thread_active = false; // Flag: 60Hz thread installed
static volatile bool tick_thread_cancel = false; // Flag: Cancel 60Hz thread
static pthread_t tick_thread; // 60Hz thread
static pthread_attr_t tick_thread_attr; // 60Hz thread attributes
static SDL_Thread *tick_thread; // 60Hz thread
static pthread_mutex_t intflag_lock = PTHREAD_MUTEX_INITIALIZER; // Mutex to protect InterruptFlags
#define LOCK_INTFLAGS pthread_mutex_lock(&intflag_lock)
#define UNLOCK_INTFLAGS pthread_mutex_unlock(&intflag_lock)
#else
#define LOCK_INTFLAGS
#define UNLOCK_INTFLAGS
#endif
static SDL_mutex *intflag_lock = NULL; // Mutex to protect InterruptFlags
#define LOCK_INTFLAGS SDL_LockMutex(intflag_lock)
#define UNLOCK_INTFLAGS SDL_UnlockMutex(intflag_lock)
#if USE_SCRATCHMEM_SUBTERFUGE
uint8 *ScratchMem = NULL; // Scratch memory for Mac ROM writes
@ -124,8 +114,8 @@ static const char *gui_connection_path = NULL; // GUI connection identifier
// Prototypes
static void *xpram_func(void *arg);
static void *tick_func(void *arg);
static int xpram_func(void *arg);
static int tick_func(void *arg);
static void one_tick(...);
@ -482,11 +472,10 @@ int main(int argc, char **argv)
#ifndef USE_CPU_EMUL_SERVICES
#if defined(HAVE_PTHREADS)
#ifdef USE_SDL
// POSIX threads available, start 60Hz thread
Set_pthread_attr(&tick_thread_attr, 0);
tick_thread_active = (pthread_create(&tick_thread, &tick_thread_attr, tick_func, NULL) == 0);
// SDL threads available, start 60Hz thread
tick_thread_active = ((tick_thread = SDL_CreateThread(tick_func, NULL)) != NULL);
if (!tick_thread_active) {
sprintf(str, GetString(STR_TICK_THREAD_ERR), strerror(errno));
ErrorAlert(str);
@ -494,60 +483,13 @@ int main(int argc, char **argv)
}
D(bug("60Hz thread started\n"));
#elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
// POSIX.4 timers and real-time signals available, start 60Hz timer
sigemptyset(&timer_sa.sa_mask);
timer_sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))one_tick;
timer_sa.sa_flags = SA_SIGINFO | SA_RESTART;
if (sigaction(SIG_TIMER, &timer_sa, NULL) < 0) {
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIG_TIMER", strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
struct sigevent timer_event;
timer_event.sigev_notify = SIGEV_SIGNAL;
timer_event.sigev_signo = SIG_TIMER;
if (timer_create(CLOCK_REALTIME, &timer_event, &timer) < 0) {
sprintf(str, GetString(STR_TIMER_CREATE_ERR), strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
struct itimerspec req;
req.it_value.tv_sec = 0;
req.it_value.tv_nsec = 16625000;
req.it_interval.tv_sec = 0;
req.it_interval.tv_nsec = 16625000;
if (timer_settime(timer, 0, &req, NULL) < 0) {
sprintf(str, GetString(STR_TIMER_SETTIME_ERR), strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
D(bug("60Hz timer started\n"));
#else
// Start 60Hz timer
sigemptyset(&timer_sa.sa_mask); // Block virtual 68k interrupts during SIGARLM handling
timer_sa.sa_handler = one_tick;
timer_sa.sa_flags = SA_ONSTACK | SA_RESTART;
if (sigaction(SIGALRM, &timer_sa, NULL) < 0) {
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGALRM", strerror(errno));
ErrorAlert(str);
QuitEmulator();
}
struct itimerval req;
req.it_interval.tv_sec = req.it_value.tv_sec = 0;
req.it_interval.tv_usec = req.it_value.tv_usec = 16625;
setitimer(ITIMER_REAL, &req, NULL);
#endif
#endif
#ifdef USE_PTHREADS_SERVICES
#ifdef USE_SDL
// Start XPRAM watchdog thread
memcpy(last_xpram, XPRAM, XPRAM_SIZE);
xpram_thread_active = (pthread_create(&xpram_thread, NULL, xpram_func, NULL) == 0);
xpram_thread_active = ((xpram_thread = SDL_CreateThread(xpram_func, NULL)) != NULL);
D(bug("XPRAM thread started\n"));
#endif
@ -573,41 +515,17 @@ void QuitEmulator(void)
Exit680x0();
#endif
#if defined(USE_CPU_EMUL_SERVICES)
// Show statistics
uint64 emulated_ticks_end = GetTicks_usec();
D(bug("%ld ticks in %ld usec = %f ticks/sec [%ld tick checks]\n",
(long)emulated_ticks_count, (long)(emulated_ticks_end - emulated_ticks_start),
emulated_ticks_count * 1000000.0 / (emulated_ticks_end - emulated_ticks_start), (long)n_check_ticks));
#elif defined(USE_PTHREADS_SERVICES)
// Stop 60Hz thread
if (tick_thread_active) {
tick_thread_cancel = true;
#ifdef HAVE_PTHREAD_CANCEL
pthread_cancel(tick_thread);
#endif
pthread_join(tick_thread, NULL);
SDL_WaitThread(tick_thread, NULL);
}
#elif defined(HAVE_TIMER_CREATE) && defined(_POSIX_REALTIME_SIGNALS)
// Stop 60Hz timer
timer_delete(timer);
#else
struct itimerval req;
req.it_interval.tv_sec = req.it_value.tv_sec = 0;
req.it_interval.tv_usec = req.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &req, NULL);
#endif
#ifdef USE_PTHREADS_SERVICES
// Stop XPRAM watchdog thread
if (xpram_thread_active) {
xpram_thread_cancel = true;
#ifdef HAVE_PTHREAD_CANCEL
pthread_cancel(xpram_thread);
#endif
pthread_join(xpram_thread, NULL);
SDL_WaitThread(xpram_thread, NULL);
}
#endif
// Deinitialize everything
ExitAll();
@ -659,71 +577,14 @@ void FlushCodeCache(void *start, uint32 size)
#endif
}
#ifdef HAVE_PTHREADS
/*
* Pthread configuration
*/
void Set_pthread_attr(pthread_attr_t *attr, int priority)
{
pthread_attr_init(attr);
#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
// Some of these only work for superuser
if (geteuid() == 0) {
pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(attr, SCHED_FIFO);
struct sched_param fifo_param;
fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) +
sched_get_priority_max(SCHED_FIFO)) / 2 +
priority);
pthread_attr_setschedparam(attr, &fifo_param);
}
if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) {
#ifdef PTHREAD_SCOPE_BOUND_NP
// If system scope is not available (eg. we're not running
// with CAP_SCHED_MGT capability on an SGI box), try bound
// scope. It exposes pthread scheduling to the kernel,
// without setting realtime priority.
pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP);
#endif
}
#endif
}
#endif // HAVE_PTHREADS
/*
* Mutexes
*/
#ifdef HAVE_PTHREADS
struct B2_mutex {
B2_mutex() {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
// Initialize the mutex for priority inheritance --
// required for accurate timing.
#if defined(HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL) && !defined(__CYGWIN__)
pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
#endif
#if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL)
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
#endif
#ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
#endif
pthread_mutex_init(&m, &attr);
pthread_mutexattr_destroy(&attr);
}
~B2_mutex() {
pthread_mutex_trylock(&m); // Make sure it's locked before
pthread_mutex_unlock(&m); // unlocking it.
pthread_mutex_destroy(&m);
}
pthread_mutex_t m;
B2_mutex() { m = SDL_CreateMutex(); }
~B2_mutex() { if (m) SDL_DestroyMutex(m); }
SDL_mutex *m;
};
B2_mutex *B2_create_mutex(void)
@ -733,12 +594,14 @@ B2_mutex *B2_create_mutex(void)
void B2_lock_mutex(B2_mutex *mutex)
{
pthread_mutex_lock(&mutex->m);
if (mutex)
SDL_LockMutex(mutex->m);
}
void B2_unlock_mutex(B2_mutex *mutex)
{
pthread_mutex_unlock(&mutex->m);
if (mutex)
SDL_UnlockMutex(mutex->m);
}
void B2_delete_mutex(B2_mutex *mutex)
@ -746,33 +609,6 @@ void B2_delete_mutex(B2_mutex *mutex)
delete mutex;
}
#else
struct B2_mutex {
int dummy;
};
B2_mutex *B2_create_mutex(void)
{
return new B2_mutex;
}
void B2_lock_mutex(B2_mutex *mutex)
{
}
void B2_unlock_mutex(B2_mutex *mutex)
{
}
void B2_delete_mutex(B2_mutex *mutex)
{
delete mutex;
}
#endif
/*
* Interrupt flags (must be handled atomically!)
*/
@ -808,17 +644,15 @@ static void xpram_watchdog(void)
}
}
#ifdef USE_PTHREADS_SERVICES
static void *xpram_func(void *arg)
static int xpram_func(void *arg)
{
while (!xpram_thread_cancel) {
for (int i=0; i<60 && !xpram_thread_cancel; i++)
Delay_usec(999999); // Only wait 1 second so we quit promptly when xpram_thread_cancel becomes true
xpram_watchdog();
}
return NULL;
return 0;
}
#endif
/*
@ -832,14 +666,6 @@ static void one_second(void)
SetInterruptFlag(INTFLAG_1HZ);
TriggerInterrupt();
#ifndef USE_PTHREADS_SERVICES
static int second_counter = 0;
if (++second_counter > 60) {
second_counter = 0;
xpram_watchdog();
}
#endif
}
static void one_tick(...)
@ -850,16 +676,6 @@ static void one_tick(...)
one_second();
}
#ifndef USE_PTHREADS_SERVICES
// Threads not used to trigger interrupts, perform video refresh from here
VideoRefresh();
#endif
#ifndef HAVE_PTHREADS
// No threads available, perform networking from here
SetInterruptFlag(INTFLAG_ETHER);
#endif
// Trigger 60Hz interrupt
if (ROMVersion != ROM_VERSION_CLASSIC || HasMacStarted()) {
SetInterruptFlag(INTFLAG_60HZ);
@ -867,8 +683,7 @@ static void one_tick(...)
}
}
#ifdef USE_PTHREADS_SERVICES
static void *tick_func(void *arg)
static int tick_func(void *arg)
{
uint64 start = GetTicks_usec();
int64 ticks = 0;
@ -878,17 +693,15 @@ static void *tick_func(void *arg)
next += 16625;
int64 delay = next - GetTicks_usec();
if (delay > 0)
Delay_usec(delay);
Delay_usec(uint32(delay));
else if (delay < -16625)
next = GetTicks_usec();
ticks++;
}
uint64 end = GetTicks_usec();
D(bug("%lld ticks in %lld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
return NULL;
D(bug("%Ld ticks in %Ld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
return 0;
}
#endif
/*
* Display error alert

View File

@ -315,51 +315,54 @@ void Delay_usec(uint32 usec)
* Suspend emulator thread, virtual CPU in idle mode
*/
#ifdef HAVE_PTHREADS
#if defined(HAVE_PTHREAD_COND_INIT)
#define IDLE_USES_COND_WAIT 1
static pthread_mutex_t idle_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t idle_cond = PTHREAD_COND_INITIALIZER;
#elif defined(HAVE_SEM_INIT)
#define IDLE_USES_SEMAPHORE 1
#include <semaphore.h>
#ifdef HAVE_SPINLOCKS
static spinlock_t idle_lock = SPIN_LOCK_UNLOCKED;
#define LOCK_IDLE spin_lock(&idle_lock)
#define UNLOCK_IDLE spin_unlock(&idle_lock)
#else
static pthread_mutex_t idle_lock = PTHREAD_MUTEX_INITIALIZER;
#define LOCK_IDLE pthread_mutex_lock(&idle_lock)
#define UNLOCK_IDLE pthread_mutex_unlock(&idle_lock)
#endif
static sem_t idle_sem;
static int idle_sem_ok = -1;
#endif
#endif
// #ifdef HAVE_PTHREADS
// #if defined(HAVE_PTHREAD_COND_INIT)
// #define IDLE_USES_COND_WAIT 1
// static pthread_mutex_t idle_lock = PTHREAD_MUTEX_INITIALIZER;
// static pthread_cond_t idle_cond = PTHREAD_COND_INITIALIZER;
// #elif defined(HAVE_SEM_INIT)
// #define IDLE_USES_SEMAPHORE 1
// #include <semaphore.h>
// #ifdef HAVE_SPINLOCKS
// static spinlock_t idle_lock = SPIN_LOCK_UNLOCKED;
// #define LOCK_IDLE spin_lock(&idle_lock)
// #define UNLOCK_IDLE spin_unlock(&idle_lock)
// #else
// static pthread_mutex_t idle_lock = PTHREAD_MUTEX_INITIALIZER;
// #define LOCK_IDLE pthread_mutex_lock(&idle_lock)
// #define UNLOCK_IDLE pthread_mutex_unlock(&idle_lock)
// #endif
// static sem_t idle_sem;
// static int idle_sem_ok = -1;
// #endif
// #endif
void idle_wait(void)
{
#ifdef IDLE_USES_COND_WAIT
pthread_mutex_lock(&idle_lock);
pthread_cond_wait(&idle_cond, &idle_lock);
pthread_mutex_unlock(&idle_lock);
#else
#ifdef IDLE_USES_SEMAPHORE
LOCK_IDLE;
if (idle_sem_ok < 0)
idle_sem_ok = (sem_init(&idle_sem, 0, 0) == 0);
if (idle_sem_ok > 0) {
idle_sem_ok++;
UNLOCK_IDLE;
sem_wait(&idle_sem);
return;
}
UNLOCK_IDLE;
#endif
//This causes events to not process randomly in JIT so commented out
usleep(10);
// Fallback: sleep 10 ms
Delay_usec(10000);
#endif
// #ifdef IDLE_USES_COND_WAIT
// pthread_mutex_lock(&idle_lock);
// pthread_cond_wait(&idle_cond, &idle_lock);
// pthread_mutex_unlock(&idle_lock);
// #else
// #ifdef IDLE_USES_SEMAPHORE
// LOCK_IDLE;
// if (idle_sem_ok < 0)
// idle_sem_ok = (sem_init(&idle_sem, 0, 0) == 0);
// if (idle_sem_ok > 0) {
// idle_sem_ok++;
// UNLOCK_IDLE;
// sem_wait(&idle_sem);
// return;
// }
// UNLOCK_IDLE;
// #endif
// // Fallback: sleep 10 ms
// Delay_usec(10000);
// #endif
}
@ -369,18 +372,19 @@ void idle_wait(void)
void idle_resume(void)
{
#ifdef IDLE_USES_COND_WAIT
pthread_cond_signal(&idle_cond);
#else
#ifdef IDLE_USES_SEMAPHORE
LOCK_IDLE;
if (idle_sem_ok > 1) {
idle_sem_ok--;
UNLOCK_IDLE;
sem_post(&idle_sem);
return;
}
UNLOCK_IDLE;
#endif
#endif
//This causes events to not process randomly in JIT so commented out
// #ifdef IDLE_USES_COND_WAIT
// pthread_cond_signal(&idle_cond);
// #else
// #ifdef IDLE_USES_SEMAPHORE
// LOCK_IDLE;
// if (idle_sem_ok > 1) {
// idle_sem_ok--;
// UNLOCK_IDLE;
// sem_post(&idle_sem);
// return;
// }
// UNLOCK_IDLE;
// #endif
// #endif
}

View File

@ -159,7 +159,7 @@ void TriggerInterrupt(void)
void TriggerNMI(void)
{
//!! not implemented yet
SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI
}

View File

@ -35,6 +35,11 @@
// #include "sysconfig.h"
#include "newcpu.h"
#ifdef __x86_64__
#define CPU_64_BIT 1
#define CPU_x86_64 1
#endif
#ifdef UAE
#ifdef CPU_64_BIT
typedef uae_u64 uintptr;

View File

@ -43,6 +43,12 @@
#error "Only [LS]AHF scheme to [gs]et flags is supported with the JIT Compiler"
#endif
//TODO: detect i386 and arm platforms
#ifdef __x86_64__
#define CPU_x86_64 1
#endif
/* NOTE: support for AMD64 assumes translation cache and other code
* buffers are allocated into a 32-bit address space because (i) B2/JIT
* code is not 64-bit clean and (ii) it's faster to resolve branches
@ -254,7 +260,7 @@ uae_u8* comp_pc_p;
#else
// External variables
// newcpu.cpp
extern int quit_program;
extern bool quit_program;
#endif
// gb-- Extra data for Basilisk II/JIT
@ -4401,41 +4407,28 @@ void flush_icache_range(uae_u8 *start_p, uae_u32 length)
blockinfo *bi = active;
while (bi) {
#if USE_CHECKSUM_INFO
bool candidate = false;
for (checksum_info *csi = bi->csi; csi; csi = csi->next) {
if (((start_p - csi->start_p) < csi->length) ||
((csi->start_p - start_p) < length)) {
candidate = true;
break;
}
}
bool invalidate = false;
for (checksum_info *csi = bi->csi; csi && !invalidate; csi = csi->next)
invalidate = (((start_p - csi->start_p) < csi->length) ||
((csi->start_p - start_p) < length));
#else
// Assume system is consistent and would invalidate the right range
const bool candidate = (bi->pc_p - start_p) < length;
const bool invalidate = (bi->pc_p - start_p) < length;
#endif
blockinfo *dbi = bi;
bi = bi->next;
if (candidate) {
uae_u32 cl = cacheline(dbi->pc_p);
if (dbi->status == BI_INVALID || dbi->status == BI_NEED_RECOMP) {
if (dbi == cache_tags[cl+1].bi)
if (invalidate) {
uae_u32 cl = cacheline(bi->pc_p);
if (bi == cache_tags[cl + 1].bi)
cache_tags[cl].handler = (cpuop_func *)popall_execute_normal;
dbi->handler_to_use = (cpuop_func *)popall_execute_normal;
set_dhtu(dbi, dbi->direct_pen);
dbi->status = BI_INVALID;
}
else {
if (dbi == cache_tags[cl+1].bi)
cache_tags[cl].handler = (cpuop_func *)popall_check_checksum;
dbi->handler_to_use = (cpuop_func *)popall_check_checksum;
set_dhtu(dbi, dbi->direct_pcc);
dbi->status = BI_NEED_CHECK;
}
remove_from_list(dbi);
add_to_dormant(dbi);
bi->handler_to_use = (cpuop_func *)popall_execute_normal;
set_dhtu(bi, bi->direct_pen);
bi->status = BI_NEED_RECOMP;
}
bi = bi->next;
}
return;
#else
// UNUSED(start);
// UNUSED(length);
#endif
flush_icache(-1);
}
@ -5138,15 +5131,11 @@ void m68k_compile_execute (void)
setjmpagain:
TRY(prb) {
for (;;) {
if (quit_program > 0) {
if (quit_program == 1) {
if (quit_program == 1) {
#if FLIGHT_RECORDER
dump_flight_recorder();
dump_flight_recorder();
#endif
break;
}
quit_program = 0;
m68k_reset ();
break;
}
m68k_do_compile_execute();
}

View File

@ -854,11 +854,11 @@ int m68k_move2c (int regno, uae_u32 *regp)
case 0: regs.sfc = *regp & 7; break;
case 1: regs.dfc = *regp & 7; break;
case 2:
cacr = *regp & (CPUType < 4 ? 0x3 : 0x80008000);
regs.cacr = *regp & (CPUType < 4 ? 0x3 : 0x80008000);
#if USE_JIT
set_cache_state(regs.cacr & 0x8000);
if (*regp & 0x08) { /* Just to be on the safe side */
flush_icache(2);
flush_icache(1);
}
#endif
break;
@ -1267,6 +1267,9 @@ void mmu_op(uae_u32 opcode, uae_u16 extra)
if ((opcode & 0xFE0) == 0x0500) {
/* PFLUSH */
mmusr = 0;
#ifdef USE_JIT
flush_icache(0);
#endif
} else if ((opcode & 0x0FD8) == 0x548) {
/* PTEST */
} else