X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fm68000%2Fm68kinterface.c;h=8dab55d7690610964ab1e6efaeaa5ab04b2548fc;hb=f005034d4a3990efc8e445ce46222ce32600411b;hp=c6e81021be9e833283dd4266d9f2dec4b4ed3ed7;hpb=b86a1645ad3fdedf85202c5563c2c5fc1e0eb03d;p=virtualjaguar diff --git a/src/m68000/m68kinterface.c b/src/m68000/m68kinterface.c index c6e8102..8dab55d 100644 --- a/src/m68000/m68kinterface.c +++ b/src/m68000/m68kinterface.c @@ -1,10 +1,10 @@ // // m68kinterface.c: Code interface to the UAE 68000 core and support code // -// by James L. Hammons +// by James Hammons // (C) 2011 Underground Software // -// JLH = James L. Hammons +// JLH = James Hammons // // Who When What // --- ---------- ------------------------------------------------------------- @@ -12,12 +12,12 @@ // #include "m68kinterface.h" +//#include #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) */ @@ -45,7 +45,7 @@ extern const struct cputbl op_smalltbl_4_ff[]; /* 68000 */ extern const struct cputbl op_smalltbl_5_ff[]; /* 68000 slow but compatible. */ // Externs, supplied by the user... -extern int irq_ack_handler(int); +//extern int irq_ack_handler(int); // Function prototypes... STATIC_INLINE void m68ki_check_interrupts(void); @@ -54,11 +54,17 @@ STATIC_INLINE uint32_t m68ki_init_exception(void); 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) @@ -77,9 +83,13 @@ cpuop_func * cpuFunctionTable[65536]; #endif #define CPU_DEBUG + + void Dasm(uint32_t offset, uint32_t qt) { #ifdef CPU_DEBUG +// back up a few instructions... +//offset -= 100; static char buffer[2048];//, mem[64]; int pc = offset, oldpc; uint32_t i; @@ -101,10 +111,39 @@ void Dasm(uint32_t offset, uint32_t qt) } +#ifdef CPU_DEBUG +void DumpRegisters(void) +{ + uint32_t i; + + for(i=0; i<16; i++) + { + printf("%s%i: %08X ", (i < 8 ? "D" : "A"), i & 0x7, regs.regs[i]); + + if ((i & 0x03) == 3) + printf("\n"); + } +} +#endif + + +void M68KDebugHalt(void) +{ + regs.spcflags |= SPCFLAG_DEBUGGER; +} + + +void M68KDebugResume(void) +{ + regs.spcflags &= ~SPCFLAG_DEBUGGER; +} + + void m68k_set_cpu_type(unsigned int type) { } + // Pulse the RESET line on the CPU void m68k_pulse_reset(void) { @@ -160,6 +199,7 @@ void m68k_pulse_reset(void) REG_PC = m68ki_read_imm_32(); m68ki_jump(REG_PC); #else + regs.spcflags = 0; regs.stopped = 0; regs.remainingCycles = 0; @@ -173,19 +213,9 @@ void m68k_pulse_reset(void) #endif } + 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 @@ -193,7 +223,6 @@ int m68k_execute(int num_cycles) return num_cycles; } -#endif #if 0 /* Set our pool of clock cycles available */ @@ -217,6 +246,17 @@ int m68k_execute(int num_cycles) /* 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) */ @@ -261,6 +301,44 @@ else if (regs.pc == 0x803422) if (inRoutine) instSeen++; +#endif +// AvP testing... (problem was: 32 bit addresses on 24 bit address cpu--FIXED) +#if 0 + static int go = 0; + + if (regs.pc == 0x94BA) + { + go = 1; + printf("\n"); + } + + if (regs.pc == 0x94C6) + go = 0; + +// if (regs.regs[10] == 0xFFFFFFFF && go) + if (go) + { +// printf("A2=-1, PC=%08X\n", regs.pc); +// go = 0; +// Dasm(regs.pc, 130); + Dasm(regs.pc, 1); + DumpRegisters(); + } +//94BA: 2468 0000 MOVEA.L (A0,$0000) == $0002328A, A2 +//94BE: 200A MOVE.L A2, D0 +//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) @@ -269,14 +347,12 @@ if (inRoutine) //} 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 */ @@ -297,20 +373,29 @@ if (inRoutine) #endif } -/* 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; @@ -320,9 +405,11 @@ void m68k_set_irq(unsigned int intLevel) m68ki_exception_interrupt(7); // Edge triggered level 7 (NMI) else m68ki_check_interrupts(); // Level triggered (IRQ) -#endif + +// pthread_mutex_unlock(&executionLock); } + // Check for interrupts STATIC_INLINE void m68ki_check_interrupts(void) { @@ -335,6 +422,7 @@ STATIC_INLINE void m68ki_check_interrupts(void) #endif } + // Service an interrupt request and start exception processing void m68ki_exception_interrupt(uint32_t intLevel) { @@ -401,12 +489,14 @@ void m68ki_exception_interrupt(uint32_t intLevel) 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!) @@ -432,9 +522,24 @@ void m68ki_exception_interrupt(uint32_t intLevel) // 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); @@ -443,6 +548,12 @@ void m68ki_exception_interrupt(uint32_t intLevel) 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 !!! @@ -450,6 +561,7 @@ void m68ki_exception_interrupt(uint32_t intLevel) #endif } + // Initiate exception processing STATIC_INLINE uint32_t m68ki_init_exception(void) { @@ -473,6 +585,7 @@ STATIC_INLINE uint32_t m68ki_init_exception(void) #endif } + // 3 word stack frame (68000 only) STATIC_INLINE void m68ki_stack_frame_3word(uint32_t pc, uint32_t sr) { @@ -489,6 +602,7 @@ STATIC_INLINE void m68ki_stack_frame_3word(uint32_t pc, uint32_t sr) #endif } + unsigned int m68k_get_reg(void * context, m68k_register_t reg) { if (reg <= M68K_REG_A7) @@ -506,6 +620,7 @@ unsigned int m68k_get_reg(void * context, m68k_register_t reg) return 0; } + void m68k_set_reg(m68k_register_t reg, unsigned int value) { if (reg <= M68K_REG_A7) @@ -521,6 +636,7 @@ void m68k_set_reg(m68k_register_t reg, unsigned int value) regs.regs[15] = value; } + // // Check if the instruction is a valid one // @@ -534,6 +650,7 @@ unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cp return 1; } + // Dummy functions, for now, until we prove the concept here. :-) // Temp, while we're using the Musashi disassembler... @@ -546,9 +663,16 @@ unsigned int m68k_disassemble(char * str_buff, unsigned int pc, unsigned int cpu 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