~optimized 68k execution/interruptions

~re-enabled Address Error emulation
This commit is contained in:
ekeeke31 2009-06-05 17:31:46 +00:00
parent 7bddb27c2b
commit aa970d66a6
10 changed files with 84 additions and 95 deletions

View File

@ -7,7 +7,7 @@ Genesis Plus GX 1.3.2 (??/??/????) (Eke-Eke)
* optimized SN76489 core
* modified SN76489 cut-off frequency (thanks to Steve Snake)
* added SN76489 linear interpolation using Blip Buffer (thanks to Blargg)
* added SN76489 linear synthesis using Blip Buffer (thanks to Blargg)
* added an option to boost SN76489 Noise Channel
* removed now outdated Gens YM2612 core
* improved YM2612 emulation accuracy (SSG-EG, CSM mode...) (thanks to Nemesis for his tests on real hardware)

View File

@ -26,10 +26,11 @@
***************************************************************************/
#include "shared.h"
#include "m68kcpu.h"
#define CART_CNT 26
extern int emulate_address_error;
/* Global Variables */
T_CART_HW cart_hw;
uint8 j_cart;

View File

@ -78,7 +78,7 @@ static inline void lightgun_update(int num)
if (io_reg[5] & 0x80)
{
/* External Interrupt ? */
if (reg[11] & 0x08) {irq_status &= 0xff; irq_status |= 0x12;}
if (reg[11] & 0x08) irq_status = (irq_status & ~0x40) | 0x12;
/* HVC Latch:
1) some games does not set HVC latch but instead use bigger X offset

View File

@ -157,7 +157,7 @@
* access a word or longword at an odd address.
* NOTE: This is only emulated properly for 68000 mode.
*/
#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF
#define M68K_EMULATE_ADDRESS_ERROR OPT_ON
/* Turn ON to enable logging of illegal instruction calls.

View File

@ -75,7 +75,9 @@ const char *const m68ki_cpu_names[] =
m68ki_cpu_core m68ki_cpu = {0};
#if M68K_EMULATE_ADDRESS_ERROR
#include <setjmp.h>
jmp_buf m68ki_aerr_trap;
int emulate_address_error = 0;
#endif /* M68K_EMULATE_ADDRESS_ERROR */
uint m68ki_aerr_address;
@ -505,13 +507,6 @@ static void default_instr_hook_callback(unsigned int pc)
}
#if M68K_EMULATE_ADDRESS_ERROR
#include <setjmp.h>
jmp_buf m68ki_aerr_trap;
int emulate_address_error = 0;
#endif /* M68K_EMULATE_ADDRESS_ERROR */
/* ======================================================================== */
/* ================================= API ================================== */
/* ======================================================================== */
@ -781,64 +776,42 @@ void m68k_set_cpu_type(unsigned int cpu_type)
}
}
/* Execute some instructions until we use up num_cycles clock cycles */
/* ASG: removed per-instruction interrupt checks */
INLINE int m68k_execute(int num_cycles)
/* Execute a single instruction */
INLINE int m68k_execute(void)
{
/* Make sure we're not stopped */
if(!CPU_STOPPED)
{
/* Set our pool of clock cycles available */
SET_CYCLES(num_cycles);
m68ki_initial_cycles = num_cycles;
SET_CYCLES(0);
/* Set tracing accodring to T1. (T0 is done inside instruction) */
m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
/* Set the address space for reads */
m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
/* Call external hook to peek at CPU */
m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */
/* Record previous program counter */
REG_PPC = REG_PC;
/* Read an instruction and call its handler */
REG_IR = m68ki_read_imm_16();
m68ki_instruction_jump_table[REG_IR]();
USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
/* Trace m68k_exception, if necessary */
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
/* ASG: update cycles */
USE_CYCLES(CPU_INT_CYCLES);
CPU_INT_CYCLES = 0;
/* Return point if we had an address error */
m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
/* Main loop. Keep going until we run out of clock cycles */
do
{
/* Set tracing accodring to T1. (T0 is done inside instruction) */
m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
/* Set the address space for reads */
m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
/* Call external hook to peek at CPU */
m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */
/* Record previous program counter */
REG_PPC = REG_PC;
/* Read an instruction and call its handler */
REG_IR = m68ki_read_imm_16();
m68ki_instruction_jump_table[REG_IR]();
USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
/* Trace m68k_exception, if necessary */
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
} while(GET_CYCLES() > 0);
/* set previous PC to current PC for the next entry into the loop */
REG_PPC = REG_PC;
/* ASG: update cycles */
USE_CYCLES(CPU_INT_CYCLES);
CPU_INT_CYCLES = 0;
/* return how many clocks we used */
return m68ki_initial_cycles - GET_CYCLES();
}
return - GET_CYCLES();
/* We get here if the CPU is stopped or halted */
SET_CYCLES(0);
CPU_INT_CYCLES = 0;
return num_cycles;
}
/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
@ -858,12 +831,23 @@ INLINE void m68k_set_irq(unsigned int int_level)
m68ki_check_interrupts(); /* Level triggered (IRQ) */
}
extern uint16 irq_status;
extern uint8 irq_status;
extern uint32 count_m68k;
void m68k_run (int cyc)
{
/* Make sure we're not stopped */
if(CPU_STOPPED)
{
count_m68k = cyc;
return;
}
int temp;
/* Return point if we had an address error */
m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
while (count_m68k < cyc)
{
/* check interrupt updates */
@ -871,18 +855,23 @@ void m68k_run (int cyc)
{
irq_status &= ~0x10;
temp = irq_status & 6;
/* hardware latency */
temp = irq_status >> 8;
if (temp) count_m68k += m68k_execute(temp);
if (irq_status & 0x40)
count_m68k += m68k_execute();
/* interrupt level */
temp = irq_status & 6;
if (temp == 6) irq_status |= 0x20;
m68k_set_irq(temp);
/* ASG: update cycles */
count_m68k += CPU_INT_CYCLES;
CPU_INT_CYCLES = 0;
}
/* execute a single instruction */
count_m68k += m68k_execute(1);
count_m68k += m68k_execute();
}
}

View File

@ -554,7 +554,7 @@
#if M68K_EMULATE_ADDRESS_ERROR
#include <setjmp.h>
extern jmp_buf m68ki_aerr_trap;
extern int emulate_address_error;
extern int emulate_address_error;
#define m68ki_set_address_error_trap() \
if(setjmp(m68ki_aerr_trap) != 0) \
@ -564,7 +564,6 @@
{ \
SET_CYCLES(0); \
CPU_INT_CYCLES = 0; \
return m68ki_initial_cycles; \
} \
}
@ -1063,13 +1062,13 @@ INLINE uint m68ki_read_imm_16(void)
if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
{
CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC);
CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR));
CPU_PREF_DATA = m68k_read_immediate_32(CPU_PREF_ADDR);
}
REG_PC += 2;
return MASK_OUT_ABOVE_16(CPU_PREF_DATA >> ((2-((REG_PC-2)&2))<<3));
#else
REG_PC += 2;
return m68k_read_immediate_16(ADDRESS_68K(REG_PC-2));
return m68k_read_immediate_16(REG_PC-2);
#endif /* M68K_EMULATE_PREFETCH */
}
INLINE uint m68ki_read_imm_32(void)
@ -1082,14 +1081,14 @@ INLINE uint m68ki_read_imm_32(void)
if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
{
CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC);
CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR));
CPU_PREF_DATA = m68k_read_immediate_32(CPU_PREF_ADDR);
}
temp_val = CPU_PREF_DATA;
REG_PC += 2;
if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
{
CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC);
CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR));
CPU_PREF_DATA = m68k_read_immediate_32(CPU_PREF_ADDR);
temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | (CPU_PREF_DATA >> 16));
}
REG_PC += 2;
@ -1099,7 +1098,7 @@ INLINE uint m68ki_read_imm_32(void)
m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
REG_PC += 4;
return m68k_read_immediate_32(ADDRESS_68K(REG_PC-4));
return m68k_read_immediate_32(REG_PC-4);
#endif /* M68K_EMULATE_PREFETCH */
}
@ -1119,7 +1118,7 @@ INLINE uint m68ki_read_8_fc(uint address, uint fc)
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
if (temp->read8) return (*temp->read8)(address);
if (temp->read8) return (*temp->read8)(ADDRESS_68K(address));
else return READ_BYTE(temp->base, (address) & 0xffff);
}
INLINE uint m68ki_read_16_fc(uint address, uint fc)
@ -1128,7 +1127,7 @@ INLINE uint m68ki_read_16_fc(uint address, uint fc)
m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
if (temp->read16) return (*temp->read16)(address);
if (temp->read16) return (*temp->read16)(ADDRESS_68K(address));
else return *(uint16 *)(temp->base + ((address) & 0xffff));
}
INLINE uint m68ki_read_32_fc(uint address, uint fc)
@ -1137,7 +1136,7 @@ INLINE uint m68ki_read_32_fc(uint address, uint fc)
m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
if (temp->read16) return ((*temp->read16)(address) << 16) | ((*temp->read16)(address + 2));
if (temp->read16) return ((*temp->read16)(ADDRESS_68K(address)) << 16) | ((*temp->read16)(ADDRESS_68K(address + 2)));
else return m68k_read_immediate_32(address);
}
@ -1145,7 +1144,7 @@ INLINE void m68ki_write_8_fc(uint address, uint fc, uint value)
{
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
if (temp->write8) (*temp->write8)(address,value);
if (temp->write8) (*temp->write8)(ADDRESS_68K(address),value);
else WRITE_BYTE(temp->base, (address) & 0xffff, value);
}
INLINE void m68ki_write_16_fc(uint address, uint fc, uint value)
@ -1153,7 +1152,7 @@ INLINE void m68ki_write_16_fc(uint address, uint fc, uint value)
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
if (temp->write16) (*temp->write16)(address,value);
if (temp->write16) (*temp->write16)(ADDRESS_68K(address),value);
else *(uint16 *)(temp->base + ((address) & 0xffff)) = value;
}
INLINE void m68ki_write_32_fc(uint address, uint fc, uint value)
@ -1163,8 +1162,8 @@ INLINE void m68ki_write_32_fc(uint address, uint fc, uint value)
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
if (temp->write16)
{
(*temp->write16)(address,value>>16);
(*temp->write16)(address+2,value&0xffff);
(*temp->write16)(ADDRESS_68K(address),value>>16);
(*temp->write16)(ADDRESS_68K(address+2),value&0xffff);
}
else
{
@ -1958,7 +1957,6 @@ INLINE void m68ki_exception_address_error(void)
*/
if(CPU_RUN_MODE == RUN_MODE_BERR_AERR_RESET)
{
m68k_read_memory_8(0x00ffff01);
CPU_STOPPED = STOP_LEVEL_HALT;
return;
}
@ -1975,7 +1973,7 @@ INLINE void m68ki_exception_address_error(void)
/* Service an interrupt request and start exception processing */
void m68ki_exception_interrupt(uint int_level)
INLINE void m68ki_exception_interrupt(uint int_level)
{
uint vector;
uint sr;

View File

@ -7,20 +7,20 @@
#define READ_WORD(BASE, ADDR) (((BASE)[ADDR]<<8) | (BASE)[(ADDR)+1])
#define READ_WORD_LONG(BASE, ADDR) (((BASE)[ADDR]<<24) | \
((BASE)[(ADDR)+1]<<16) | \
((BASE)[(ADDR)+2]<<8) | \
(BASE)[(ADDR)+3])
#define READ_WORD_LONG(BASE, ADDR) (((BASE)[(ADDR)+1]<<24) | \
((BASE)[(ADDR)]<<16) | \
((BASE)[(ADDR)+3]<<8) | \
(BASE)[(ADDR)+1])
#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[(ADDR)^1] = (VAL)&0xff
#define WRITE_WORD(BASE, ADDR, VAL) (BASE)[ADDR] = ((VAL)>>8) & 0xff; \
(BASE)[(ADDR)+1] = (VAL)&0xff
#define WRITE_WORD_LONG(BASE, ADDR, VAL) (BASE)[(ADDR] = ((VAL)>>24) & 0xff; \
(BASE)[(ADDR)+1] = ((VAL)>>16)&0xff; \
(BASE)[(ADDR)+2] = ((VAL)>>8)&0xff; \
(BASE)[(ADDR)+3] = (VAL)&0xff
#define WRITE_WORD_LONG(BASE, ADDR, VAL) (BASE)[(ADDR+1)] = ((VAL)>>24) & 0xff; \
(BASE)[(ADDR)] = ((VAL)>>16)&0xff; \
(BASE)[(ADDR+3)] = ((VAL)>>8)&0xff; \
(BASE)[(ADDR+2)] = (VAL)&0xff
#else

View File

@ -388,7 +388,7 @@ int system_frame (int do_skip)
{
h_counter = reg[10];
hint_pending = 1;
if (reg[0] & 0x10) irq_status = (irq_status & 0xff) | 0x14;
if (reg[0] & 0x10) irq_status = (irq_status & ~0x40) | 0x14;
/* adjust timings to take further decrement in account (see below) */
if ((line != 0) || (h_counter == 0)) aim_m68k += 36;
@ -430,10 +430,11 @@ int system_frame (int do_skip)
/* V Interrupt */
status |= 0x80;
vint_pending = 1;
/* 36 cycles latency after VINT occurence flag (Ex-Mutants, Tyrant) */
if (reg[1] & 0x20) irq_status = (irq_status & 0xff) | 0x2416;
m68k_run(line_m68k + 113);
vint_pending = 1;
if (reg[1] & 0x20) irq_status = (irq_status & ~0x40) | 0x16;
}
else if (!do_skip)
{

View File

@ -50,7 +50,7 @@ uint16 status; /* VDP status flags */
uint8 dmafill; /* next VDP Write is DMA Fill */
uint8 hint_pending; /* 0= Line interrupt is pending */
uint8 vint_pending; /* 1= Frame interrupt is pending */
uint16 irq_status; /* Interrupt lines updated */
uint8 irq_status; /* Interrupt lines updated */
/* Global variables */
uint16 ntab; /* Name table A base address */
@ -651,7 +651,7 @@ static inline void reg_w(unsigned int r, unsigned int d)
{
/* update IRQ status */
irq_status &= 0x20;
irq_status |= 0x10;
irq_status |= 0x50;
if (vint_pending && (reg[1] & 0x20)) irq_status |= 6;
else if (d & 0x10) irq_status |= 4;
}
@ -677,7 +677,7 @@ static inline void reg_w(unsigned int r, unsigned int d)
{
/* update IRQ status */
irq_status &= 0x20;
irq_status |= 0x110;
irq_status |= 0x50;
if (d & 0x20) irq_status |= 6;
else if (hint_pending && (reg[0] & 0x10)) irq_status |= 4;
}
@ -697,7 +697,7 @@ static inline void reg_w(unsigned int r, unsigned int d)
}
/* Display activated/blanked during Horizontal Blanking */
if (((d&0x40) != (reg[1]&0x40)) && (v_counter < bitmap.viewport.h))
if (((d&0x40) != (reg[1]&0x40)) && !(status & 8))
{
if (count_m68k <= (hint_m68k + 120))
{
@ -748,7 +748,7 @@ static inline void reg_w(unsigned int r, unsigned int d)
color_update(0x00, *(uint16 *)&cram[(border << 1)]);
/* background color modified during Horizontal Blanking */
if ((v_counter < bitmap.viewport.h) && (count_m68k <= (line_m68k + 84)))
if (!(status & 8) && (count_m68k <= (line_m68k + 84)))
{
/* remap current line (see Road Rash I,II,III) */
reg[7] = d;

View File

@ -38,7 +38,7 @@ extern uint16 status;
extern uint8 dmafill;
extern uint8 hint_pending;
extern uint8 vint_pending;
extern uint16 irq_status;
extern uint8 irq_status;
/* Global variables */
extern uint16 ntab;