//
#include "m68kinterface.h"
+//#include <pthread.h>
#include "cpudefs.h"
#include "inlines.h"
#include "cpuextra.h"
#include "readcpu.h"
-
// Exception Vectors handled by emulation
#define EXCEPTION_BUS_ERROR 2 /* This one is not emulated! */
#define EXCEPTION_ADDRESS_ERROR 3 /* This one is partially emulated (doesn't stack a proper frame yet) */
STATIC_INLINE void m68ki_stack_frame_3word(uint32_t pc, uint32_t sr);
unsigned long IllegalOpcode(uint32_t opcode);
void BuildCPUFunctionTable(void);
+void m68k_set_irq2(unsigned int intLevel);
// Local "Global" vars
static int32_t initialCycles;
cpuop_func * cpuFunctionTable[65536];
+// By virtue of the fact that m68k_set_irq() can be called asychronously by
+// another thread, we need something along the lines of this:
+static int checkForIRQToHandle = 0;
+//static pthread_mutex_t executionLock = PTHREAD_MUTEX_INITIALIZER;
+static int IRQLevelToHandle = 0;
#if 0
#define ADD_CYCLES(A) m68ki_remaining_cycles += (A)
#endif
+void M68KDebugHalt(void)
+{
+ regs.spcflags |= SPCFLAG_DEBUGGER;
+}
+
+
+void M68KDebugResume(void)
+{
+ regs.spcflags &= ~SPCFLAG_DEBUGGER;
+}
+
+
void m68k_set_cpu_type(unsigned int type)
{
}
REG_PC = m68ki_read_imm_32();
m68ki_jump(REG_PC);
#else
+ regs.spcflags = 0;
regs.stopped = 0;
regs.remainingCycles = 0;
int m68k_execute(int num_cycles)
{
-#if 0
- /* Make sure we're not stopped */
- if (CPU_STOPPED)
- {
- /* We get here if the CPU is stopped or halted */
- SET_CYCLES(0);
- CPU_INT_CYCLES = 0;
-
- return num_cycles;
- }
-#else
if (regs.stopped)
{
regs.remainingCycles = 0; // int32_t
return num_cycles;
}
-#endif
#if 0
/* Set our pool of clock cycles available */
/* Main loop. Keep going until we run out of clock cycles */
do
{
+ // This is so our debugging code can break in on a dime.
+ // Otherwise, this is just extra slow down :-P
+ if (regs.spcflags & SPCFLAG_DEBUGGER)
+ {
+ // Not sure this is correct... :-P
+ num_cycles = initialCycles - regs.remainingCycles;
+ regs.remainingCycles = 0; // int32_t
+ regs.interruptCycles = 0; // uint32_t
+
+ return num_cycles;
+ }
#if 0
/* Set tracing accodring to T1. (T0 is done inside instruction) */
m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
//94C0: 6A02 BPL.B $94C4
//94C2: 2452 MOVEA.L (A2), A2 ; <--- HERE
//94C4: 4283 CLR.L D3
+#endif
+// pthread_mutex_lock(&executionLock);
+ if (checkForIRQToHandle)
+ {
+ checkForIRQToHandle = 0;
+ m68k_set_irq2(IRQLevelToHandle);
+ }
+
+#ifdef M68K_HOOK_FUNCTION
+ M68KInstructionHook();
#endif
uint32_t opcode = get_iword(0);
//if ((opcode & 0xFFF8) == 0x31C0)
//}
int32_t cycles = (int32_t)(*cpuFunctionTable[opcode])(opcode);
regs.remainingCycles -= cycles;
+// pthread_mutex_unlock(&executionLock);
+
//printf("Executed opcode $%04X (%i cycles)...\n", opcode, cycles);
#endif
}
-#if 0
- while (GET_CYCLES() > 0);
-#else
while (regs.remainingCycles > 0);
-#endif
#if 0
/* set previous PC to current PC for the next entry into the loop */
}
-/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
void m68k_set_irq(unsigned int intLevel)
{
-#if 0
- uint old_level = CPU_INT_LEVEL;
- CPU_INT_LEVEL = int_level << 8;
+ // We need to check for stopped state as well...
+ if (regs.stopped)
+ {
+ m68k_set_irq2(intLevel);
+ return;
+ }
+
+ // Since this can be called asynchronously, we need to fix it so that it
+ // doesn't fuck up the main execution loop.
+ IRQLevelToHandle = intLevel;
+ checkForIRQToHandle = 1;
+}
+
+
+/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
+void m68k_set_irq2(unsigned int intLevel)
+{
+// pthread_mutex_lock(&executionLock);
+// printf("m68k_set_irq: Could not get the lock!!!\n");
- /* A transition from < 7 to 7 always interrupts (NMI) */
- /* Note: Level 7 can also level trigger like a normal IRQ */
- if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
- m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
- else
- m68ki_check_interrupts(); /* Level triggered (IRQ) */
-#else
int oldLevel = regs.intLevel;
regs.intLevel = intLevel;
m68ki_exception_interrupt(7); // Edge triggered level 7 (NMI)
else
m68ki_check_interrupts(); // Level triggered (IRQ)
-#endif
+
+// pthread_mutex_unlock(&executionLock);
}
CPU_INT_LEVEL = 0;
#endif /* M68K_EMULATE_INT_ACK */
#else
- // Turn off the stopped state
+ // Turn off the stopped state (N.B.: normal 68K behavior!)
regs.stopped = 0;
//JLH: need to add halt state?
+// prolly, for debugging/alpine mode... :-/
+// but then again, this should be handled already by the main execution loop :-P
// If we are halted, don't do anything
-// if (CPU_STOPPED)
+// if (regs.stopped)
// return;
// Acknowledge the interrupt (NOTE: This is a user supplied function!)
// Set the interrupt mask to the level of the one being serviced
regs.intmask = intLevel;
+#if 0
+extern int startM68KTracing;
+if (startM68KTracing)
+{
+ printf("IRQ: old PC=%06X, ", regs.pc);
+}
+#endif
+
// Get the new PC
uint32_t newPC = m68k_read_memory_32(vector << 2);
+#if 0
+if (startM68KTracing)
+{
+ printf("new PC=%06X, vector=%u, ", newPC, vector);
+}
+#endif
+
// If vector is uninitialized, call the uninitialized interrupt vector
if (newPC == 0)
newPC = m68k_read_memory_32(EXCEPTION_UNINITIALIZED_INTERRUPT << 2);
m68ki_stack_frame_3word(regs.pc, sr);
m68k_setpc(newPC);
+#if 0
+if (startM68KTracing)
+{
+ printf("(PC=%06X)\n", regs.pc);
+}
+#endif
// Defer cycle counting until later
regs.interruptCycles += 56; // NOT ACCURATE-- !!! FIX !!!
int m68k_cycles_run(void) {} /* Number of cycles run so far */
int m68k_cycles_remaining(void) {} /* Number of cycles left */
-void m68k_modify_timeslice(int cycles) {} /* Modify cycles left */
+//void m68k_modify_timeslice(int cycles) {} /* Modify cycles left */
//void m68k_end_timeslice(void) {} /* End timeslice now */
+void m68k_modify_timeslice(int cycles)
+{
+ regs.remainingCycles = cycles;
+}
+
+
void m68k_end_timeslice(void)
{
#if 0