it isn't safe to do cross-thread communication with multiple variables
unless we use memory barriers between them, both on writes and reads.
In the case of musashi, it's the sequence of set irq/do_reset and reset cycles left.
This patch introduces memory barriers between the writes and reads of these
extern int m68ki_remaining_cycles;
#define M68K_SET_IRQ(i) old_level = CPU_INT_LEVEL; \
extern int m68ki_remaining_cycles;
#define M68K_SET_IRQ(i) old_level = CPU_INT_LEVEL; \
- CPU_INT_LEVEL = (i << 8); \
- if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700) \
- m68ki_cpu.nmi_pending = TRUE;
-#define M68K_END_TIMESLICE m68ki_initial_cycles = GET_CYCLES(); \
- SET_CYCLES(0);
+ CPU_INT_LEVEL = (i << 8); \
+ if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700) \
+ m68ki_cpu.nmi_pending = TRUE;
+#define M68K_END_TIMESLICE m68ki_initial_cycles = GET_CYCLES(); \
+ SET_CYCLES(0);
#else
#define M68K_SET_IRQ m68k_set_irq
#define M68K_END_TIMESLICE m68k_end_timeslice()
#endif
#define NOP asm("nop"); asm("nop"); asm("nop"); asm("nop");
#else
#define M68K_SET_IRQ m68k_set_irq
#define M68K_END_TIMESLICE m68k_end_timeslice()
#endif
#define NOP asm("nop"); asm("nop"); asm("nop"); asm("nop");
+#define MEMORY_BARRIER() __sync_synchronize()
#define DEBUG_EMULATOR
#ifdef DEBUG_EMULATOR
#define DEBUG_EMULATOR
#ifdef DEBUG_EMULATOR
- char pad0[64];
- unsigned int value;
- char pad1[64];
+ char pad0[64];
+ unsigned int value;
+ char pad1[64];
};
volatile struct DoReset do_reset = {0};
};
volatile struct DoReset do_reset = {0};
if (!(value & (1 << PIN_IPL_ZERO))) {
old_irq = irq_delay;
if (!(value & (1 << PIN_IPL_ZERO))) {
old_irq = irq_delay;
- M68K_END_TIMESLICE;
- NOP
+ MEMORY_BARRIER();
+ M68K_END_TIMESLICE;
}
}
if(do_reset.value==0)
}
}
if(do_reset.value==0)
{
printf("Amiga Reset is down...\n");
do_reset.value=1;
{
printf("Amiga Reset is down...\n");
do_reset.value=1;
M68K_END_TIMESLICE;
}
else
M68K_END_TIMESLICE;
}
else
- //usleep(0);
- //NOP NOP
noppers:
NOP NOP NOP NOP NOP NOP NOP NOP
//NOP NOP NOP NOP NOP NOP NOP NOP
noppers:
NOP NOP NOP NOP NOP NOP NOP NOP
//NOP NOP NOP NOP NOP NOP NOP NOP
- m68ki_cpu_core *state = &m68ki_cpu;
- m68k_pulse_reset(state);
+ m68ki_cpu_core *state = &m68ki_cpu;
+ m68k_pulse_reset(state);
cpu_loop:
if (mouse_hook_enabled) {
cpu_loop:
if (mouse_hook_enabled) {
printf("%.8X (%.8X)]] %s\n", m68k_get_reg(NULL, M68K_REG_PC), (m68k_get_reg(NULL, M68K_REG_PC) & 0xFFFFFF), disasm_buf);
if (do_disasm)
do_disasm--;
printf("%.8X (%.8X)]] %s\n", m68k_get_reg(NULL, M68K_REG_PC), (m68k_get_reg(NULL, M68K_REG_PC) & 0xFFFFFF), disasm_buf);
if (do_disasm)
do_disasm--;
- m68k_execute(state, 1);
+ m68k_execute(state, 1);
}
else {
if (cpu_emulation_running) {
}
else {
if (cpu_emulation_running) {
- if (irq)
- m68k_execute(state, 5);
- else
- m68k_execute(state, loop_cycles);
+ MEMORY_BARRIER();
+ if (irq)
+ m68k_execute(state, 5);
+ else
+ m68k_execute(state, loop_cycles);
while (irq) {
last_irq = ((inline_read_status_reg() & 0xe000) >> 13);
if (last_irq != 0 && last_irq != last_last_irq) {
while (irq) {
last_irq = ((inline_read_status_reg() & 0xe000) >> 13);
if (last_irq != 0 && last_irq != last_last_irq) {
M68K_SET_IRQ(last_irq);
}
m68k_execute(state, 50);
M68K_SET_IRQ(last_irq);
}
m68k_execute(state, 50);
if (!irq && last_last_irq != 0) {
//M68K_SET_IRQ(0);
last_last_irq = 0;
}
if (!irq && last_last_irq != 0) {
//M68K_SET_IRQ(0);
last_last_irq = 0;
}
if (do_reset.value) {
cpu_pulse_reset();
do_reset.value=0;
if (do_reset.value) {
cpu_pulse_reset();
do_reset.value=0;
- goto stop_cpu_emulation;
+ goto stop_cpu_emulation;
}
if (c == 'q') {
printf("Quitting and exiting emulator.\n");
}
if (c == 'q') {
printf("Quitting and exiting emulator.\n");
goto key_end;
}
if (c == 'd') {
goto key_end;
}
if (c == 'd') {
m68k_init();
printf("Setting CPU type to %d.\n", cpu_type);
m68k_init();
printf("Setting CPU type to %d.\n", cpu_type);
- m68k_set_cpu_type(&m68ki_cpu, cpu_type);
+ m68k_set_cpu_type(&m68ki_cpu, cpu_type);
cpu_pulse_reset();
pthread_t ipl_tid = 0, cpu_tid, kbd_tid;
cpu_pulse_reset();
pthread_t ipl_tid = 0, cpu_tid, kbd_tid;
}
void cpu_pulse_reset(void) {
}
void cpu_pulse_reset(void) {
- m68ki_cpu_core *state = &m68ki_cpu;
+ m68ki_cpu_core *state = &m68ki_cpu;
ps_pulse_reset();
ovl = 1;
if (cfg->platform->handle_reset)
cfg->platform->handle_reset(cfg);
ps_pulse_reset();
ovl = 1;
if (cfg->platform->handle_reset)
cfg->platform->handle_reset(cfg);
- m68k_pulse_reset(state);
+ m68k_pulse_reset(state);
}
int cpu_irq_ack(int level) {
}
int cpu_irq_ack(int level) {