~improved DIVU/DIVS/MULU/MULS timing accuracy (68k core)

~optimized 68k execution
~reverted recent changes to LFO phase modulation, need more testing (ym2162 core)
This commit is contained in:
ekeeke31 2009-06-23 16:38:29 +00:00
parent c35921ba3d
commit 4835860232
8 changed files with 486 additions and 115 deletions

View File

@ -15,7 +15,8 @@ Genesis Plus GX 1.3.2 (??/??/????) (Eke-Eke)
* added 3 Band Equalizer for improved & fully configurable sound filtering (taken from Softdev's NeoCD Redux) * added 3 Band Equalizer for improved & fully configurable sound filtering (taken from Softdev's NeoCD Redux)
* improved sprites masking emulation: fixes 3D level in Mickey Mania (thanks to Nemesis for his test program) * improved sprites masking emulation: fixes 3D level in Mickey Mania (thanks to Nemesis for his test program)
* fixed lightgun autodetection: fixes cursor position in Lethal Enforcers II * fixed lightgun autodetection: fixes cursor position in Lethal Enforcers II
* various code cleanup & optimization * improved DIVU/DVIS (thanks to Jorge Cwik) & MULU/MULS instructions timing accuracy
* lots of code cleanup & core optimizations
[Gamecube/Wii] [Gamecube/Wii]

View File

@ -0,0 +1,215 @@
/*
* Compute exact number of CPU cycles taken
* by DIVU and DIVS on a 68000 processor.
*
* Copyright (c) 2005 by Jorge Cwik, pasti@fxatari.com
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/*
The routines below take dividend and divisor as parameters.
They return 0 if division by zero, or exact number of cycles otherwise.
The number of cycles returned assumes a register operand.
Effective address time must be added if memory operand.
For 68000 only (not 68010, 68012, 68020, etc).
Probably valid for 68008 after adding the extra prefetch cycle.
Best and worst cases for register operand:
(Note the difference with the documented range.)
DIVU:
Overflow (always): 10 cycles.
Worst case: 136 cycles.
Best case: 76 cycles.
DIVS:
Absolute overflow: 16-18 cycles.
Signed overflow is not detected prematurely.
Worst case: 156 cycles.
Best case without signed overflow: 122 cycles.
Best case with signed overflow: 120 cycles
*/
#include <stdlib.h>
// Change this depending on architecture
// This code assumes long is 32 bits and short is 16 bits
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef signed long LONG;
typedef signed short SHORT;
//
// DIVU
// Unsigned division
//
unsigned getDivu68kCycles( DWORD dividend, WORD divisor)
{
int i;
//if( (WORD) divisor == 0)
// return 0;
// Overflow
//if( (dividend >> 16) >= divisor)
// return (mcycles = 5) * 2;
unsigned mcycles = 38;
DWORD hdivisor = ((DWORD) divisor) << 16;
for( i = 0; i < 15; i++)
{
DWORD temp;
temp = dividend;
dividend <<= 1;
// If carry from shift
if( (LONG) temp < 0)
{
dividend -= hdivisor;
}
else
{
mcycles += 2;
if( dividend >= hdivisor)
{
dividend -= hdivisor;
mcycles--;
}
}
}
return mcycles * 2;
}
//
// DIVS
// Signed division
//
unsigned getDivs68kCycles( LONG dividend, SHORT divisor)
{
//if( (SHORT) divisor == 0)
// return 0;
unsigned mcycles = 6;
if( dividend < 0)
mcycles++;
// Check for absolute overflow
if( ((DWORD) abs( dividend) >> 16) >= (WORD) abs( divisor))
{
return (mcycles + 2) * 2;
}
// Absolute quotient
unsigned aquot = (DWORD) abs( dividend) / (WORD) abs( divisor);
mcycles += 55;
if( divisor >= 0)
{
if( dividend >= 0)
mcycles--;
else
mcycles++;
}
// Count 15 msbits in absolute of quotient
int i;
for( i = 0; i < 15; i++)
{
if( (SHORT) aquot >= 0)
mcycles++;
aquot <<= 1;
}
return mcycles * 2;
}
//
// MULU
// Unsigned multiplication
//
unsigned getMulu68kCycles( WORD source)
{
int i;
unsigned mcycles = 38;
/* count number of bits set to 1 */
for( i = 0; i < 15; i++)
{
if (source & 1)
{
mcycles += 2;
}
source >>= 1;
}
/* 38 + 2*N */
return mcycles;
}
//
// MULS
// Signed multiplication
//
unsigned getMuls68kCycles( SHORT source)
{
int i;
unsigned mcycles = 38;
/* detect 01 or 10 patterns */
LONG temp = source << 1;
temp ^= source;
/* count number of bits set to 1 */
for( i = 0; i < 15; i++)
{
if (source & 1)
{
mcycles += 2;
}
source >>= 1;
}
/* 38 + 2*N */
return mcycles;
}

View File

@ -802,13 +802,6 @@ INLINE int m68k_execute(void)
/* Trace m68k_exception, if necessary */ /* Trace m68k_exception, if necessary */
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */ m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
/* ASG: update cycles */
USE_CYCLES(CPU_INT_CYCLES);
CPU_INT_CYCLES = 0;
/* set previous PC to current PC for the next entry into the loop */
REG_PPC = REG_PC;
/* return how many clocks we used */ /* return how many clocks we used */
return - GET_CYCLES(); return - GET_CYCLES();
@ -832,7 +825,6 @@ INLINE void m68k_set_irq(unsigned int int_level)
} }
extern uint8 irq_status; extern uint8 irq_status;
extern uint32 count_m68k;
void m68k_run (int cyc) void m68k_run (int cyc)
{ {
@ -855,12 +847,7 @@ void m68k_run (int cyc)
count_m68k += m68k_execute(); count_m68k += m68k_execute();
/* interrupt level */ /* interrupt level */
if (temp == 6) irq_status |= 0x20;
m68k_set_irq(temp); m68k_set_irq(temp);
/* ASG: update cycles */
count_m68k += CPU_INT_CYCLES;
CPU_INT_CYCLES = 0;
} }
/* Make sure we're not stopped */ /* Make sure we're not stopped */
@ -873,6 +860,10 @@ void m68k_run (int cyc)
/* execute a single instruction */ /* execute a single instruction */
count_m68k += m68k_execute(); count_m68k += m68k_execute();
} }
/* set previous PC to current PC for the next entry into the loop */
REG_PPC = REG_PC;
} }
int m68k_cycles_run(void) int m68k_cycles_run(void)

View File

@ -33,6 +33,8 @@
#include <setjmp.h> #include <setjmp.h>
#endif /* M68K_EMULATE_ADDRESS_ERROR */ #endif /* M68K_EMULATE_ADDRESS_ERROR */
extern unsigned int count_m68k;
/* ======================================================================== */ /* ======================================================================== */
/* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */ /* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */
/* ======================================================================== */ /* ======================================================================== */
@ -2036,7 +2038,7 @@ INLINE void m68ki_exception_interrupt(uint int_level)
m68ki_jump(new_pc); m68ki_jump(new_pc);
/* Defer cycle counting until later */ /* Defer cycle counting until later */
CPU_INT_CYCLES += CYC_EXCEPTION[vector]; count_m68k += CYC_EXCEPTION[vector];
//#if !M68K_EMULATE_INT_ACK //#if !M68K_EMULATE_INT_ACK
/* Automatically clear IRQ if we are not using an acknowledge scheme */ /* Automatically clear IRQ if we are not using an acknowledge scheme */

View File

@ -1,4 +1,6 @@
#include "m68kcpu.h" #include "m68kcpu.h"
#include "m68kCycleAccurate.h"
extern void m68040_fpu_op0(void); extern void m68040_fpu_op0(void);
extern void m68040_fpu_op1(void); extern void m68040_fpu_op1(void);
@ -12611,6 +12613,9 @@ static void m68k_op_divs_16_d(void)
if(src != 0) if(src != 0)
{ {
int cyc = getDivs68kCycles(*r_dst,src);
USE_CYCLES(cyc);
if((uint32)*r_dst == 0x80000000 && src == -1) if((uint32)*r_dst == 0x80000000 && src == -1)
{ {
FLAG_Z = 0; FLAG_Z = 0;
@ -12649,6 +12654,9 @@ static void m68k_op_divs_16_ai(void)
if(src != 0) if(src != 0)
{ {
int cyc = getDivs68kCycles(*r_dst,src);
USE_CYCLES(cyc);
if((uint32)*r_dst == 0x80000000 && src == -1) if((uint32)*r_dst == 0x80000000 && src == -1)
{ {
FLAG_Z = 0; FLAG_Z = 0;
@ -12687,6 +12695,9 @@ static void m68k_op_divs_16_pi(void)
if(src != 0) if(src != 0)
{ {
int cyc = getDivs68kCycles(*r_dst,src);
USE_CYCLES(cyc);
if((uint32)*r_dst == 0x80000000 && src == -1) if((uint32)*r_dst == 0x80000000 && src == -1)
{ {
FLAG_Z = 0; FLAG_Z = 0;
@ -12725,6 +12736,9 @@ static void m68k_op_divs_16_pd(void)
if(src != 0) if(src != 0)
{ {
int cyc = getDivs68kCycles(*r_dst,src);
USE_CYCLES(cyc);
if((uint32)*r_dst == 0x80000000 && src == -1) if((uint32)*r_dst == 0x80000000 && src == -1)
{ {
FLAG_Z = 0; FLAG_Z = 0;
@ -12763,6 +12777,9 @@ static void m68k_op_divs_16_di(void)
if(src != 0) if(src != 0)
{ {
int cyc = getDivs68kCycles(*r_dst,src);
USE_CYCLES(cyc);
if((uint32)*r_dst == 0x80000000 && src == -1) if((uint32)*r_dst == 0x80000000 && src == -1)
{ {
FLAG_Z = 0; FLAG_Z = 0;
@ -12801,6 +12818,9 @@ static void m68k_op_divs_16_ix(void)
if(src != 0) if(src != 0)
{ {
int cyc = getDivs68kCycles(*r_dst,src);
USE_CYCLES(cyc);
if((uint32)*r_dst == 0x80000000 && src == -1) if((uint32)*r_dst == 0x80000000 && src == -1)
{ {
FLAG_Z = 0; FLAG_Z = 0;
@ -12839,6 +12859,9 @@ static void m68k_op_divs_16_aw(void)
if(src != 0) if(src != 0)
{ {
int cyc = getDivs68kCycles(*r_dst,src);
USE_CYCLES(cyc);
if((uint32)*r_dst == 0x80000000 && src == -1) if((uint32)*r_dst == 0x80000000 && src == -1)
{ {
FLAG_Z = 0; FLAG_Z = 0;
@ -12877,6 +12900,9 @@ static void m68k_op_divs_16_al(void)
if(src != 0) if(src != 0)
{ {
int cyc = getDivs68kCycles(*r_dst,src);
USE_CYCLES(cyc);
if((uint32)*r_dst == 0x80000000 && src == -1) if((uint32)*r_dst == 0x80000000 && src == -1)
{ {
FLAG_Z = 0; FLAG_Z = 0;
@ -12915,6 +12941,9 @@ static void m68k_op_divs_16_pcdi(void)
if(src != 0) if(src != 0)
{ {
int cyc = getDivs68kCycles(*r_dst,src);
USE_CYCLES(cyc);
if((uint32)*r_dst == 0x80000000 && src == -1) if((uint32)*r_dst == 0x80000000 && src == -1)
{ {
FLAG_Z = 0; FLAG_Z = 0;
@ -12953,6 +12982,9 @@ static void m68k_op_divs_16_pcix(void)
if(src != 0) if(src != 0)
{ {
int cyc = getDivs68kCycles(*r_dst,src);
USE_CYCLES(cyc);
if((uint32)*r_dst == 0x80000000 && src == -1) if((uint32)*r_dst == 0x80000000 && src == -1)
{ {
FLAG_Z = 0; FLAG_Z = 0;
@ -12991,6 +13023,9 @@ static void m68k_op_divs_16_i(void)
if(src != 0) if(src != 0)
{ {
int cyc = getDivs68kCycles(*r_dst,src);
USE_CYCLES(cyc);
if((uint32)*r_dst == 0x80000000 && src == -1) if((uint32)*r_dst == 0x80000000 && src == -1)
{ {
FLAG_Z = 0; FLAG_Z = 0;
@ -13032,6 +13067,9 @@ static void m68k_op_divu_16_d(void)
if(quotient < 0x10000) if(quotient < 0x10000)
{ {
int cyc = getDivu68kCycles(*r_dst,src);
USE_CYCLES(cyc);
FLAG_Z = quotient; FLAG_Z = quotient;
FLAG_N = NFLAG_16(quotient); FLAG_N = NFLAG_16(quotient);
FLAG_V = VFLAG_CLEAR; FLAG_V = VFLAG_CLEAR;
@ -13039,6 +13077,7 @@ static void m68k_op_divu_16_d(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return; return;
} }
USE_CYCLES(10);
FLAG_V = VFLAG_SET; FLAG_V = VFLAG_SET;
return; return;
} }
@ -13058,6 +13097,9 @@ static void m68k_op_divu_16_ai(void)
if(quotient < 0x10000) if(quotient < 0x10000)
{ {
int cyc = getDivu68kCycles(*r_dst,src);
USE_CYCLES(cyc);
FLAG_Z = quotient; FLAG_Z = quotient;
FLAG_N = NFLAG_16(quotient); FLAG_N = NFLAG_16(quotient);
FLAG_V = VFLAG_CLEAR; FLAG_V = VFLAG_CLEAR;
@ -13065,6 +13107,7 @@ static void m68k_op_divu_16_ai(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return; return;
} }
USE_CYCLES(10);
FLAG_V = VFLAG_SET; FLAG_V = VFLAG_SET;
return; return;
} }
@ -13084,6 +13127,9 @@ static void m68k_op_divu_16_pi(void)
if(quotient < 0x10000) if(quotient < 0x10000)
{ {
int cyc = getDivu68kCycles(*r_dst,src);
USE_CYCLES(cyc);
FLAG_Z = quotient; FLAG_Z = quotient;
FLAG_N = NFLAG_16(quotient); FLAG_N = NFLAG_16(quotient);
FLAG_V = VFLAG_CLEAR; FLAG_V = VFLAG_CLEAR;
@ -13091,6 +13137,7 @@ static void m68k_op_divu_16_pi(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return; return;
} }
USE_CYCLES(10);
FLAG_V = VFLAG_SET; FLAG_V = VFLAG_SET;
return; return;
} }
@ -13110,6 +13157,9 @@ static void m68k_op_divu_16_pd(void)
if(quotient < 0x10000) if(quotient < 0x10000)
{ {
int cyc = getDivu68kCycles(*r_dst,src);
USE_CYCLES(cyc);
FLAG_Z = quotient; FLAG_Z = quotient;
FLAG_N = NFLAG_16(quotient); FLAG_N = NFLAG_16(quotient);
FLAG_V = VFLAG_CLEAR; FLAG_V = VFLAG_CLEAR;
@ -13117,6 +13167,7 @@ static void m68k_op_divu_16_pd(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return; return;
} }
USE_CYCLES(10);
FLAG_V = VFLAG_SET; FLAG_V = VFLAG_SET;
return; return;
} }
@ -13136,6 +13187,9 @@ static void m68k_op_divu_16_di(void)
if(quotient < 0x10000) if(quotient < 0x10000)
{ {
int cyc = getDivu68kCycles(*r_dst,src);
USE_CYCLES(cyc);
FLAG_Z = quotient; FLAG_Z = quotient;
FLAG_N = NFLAG_16(quotient); FLAG_N = NFLAG_16(quotient);
FLAG_V = VFLAG_CLEAR; FLAG_V = VFLAG_CLEAR;
@ -13143,6 +13197,7 @@ static void m68k_op_divu_16_di(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return; return;
} }
USE_CYCLES(10);
FLAG_V = VFLAG_SET; FLAG_V = VFLAG_SET;
return; return;
} }
@ -13162,6 +13217,9 @@ static void m68k_op_divu_16_ix(void)
if(quotient < 0x10000) if(quotient < 0x10000)
{ {
int cyc = getDivu68kCycles(*r_dst,src);
USE_CYCLES(cyc);
FLAG_Z = quotient; FLAG_Z = quotient;
FLAG_N = NFLAG_16(quotient); FLAG_N = NFLAG_16(quotient);
FLAG_V = VFLAG_CLEAR; FLAG_V = VFLAG_CLEAR;
@ -13169,6 +13227,7 @@ static void m68k_op_divu_16_ix(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return; return;
} }
USE_CYCLES(10);
FLAG_V = VFLAG_SET; FLAG_V = VFLAG_SET;
return; return;
} }
@ -13188,6 +13247,9 @@ static void m68k_op_divu_16_aw(void)
if(quotient < 0x10000) if(quotient < 0x10000)
{ {
int cyc = getDivu68kCycles(*r_dst,src);
USE_CYCLES(cyc);
FLAG_Z = quotient; FLAG_Z = quotient;
FLAG_N = NFLAG_16(quotient); FLAG_N = NFLAG_16(quotient);
FLAG_V = VFLAG_CLEAR; FLAG_V = VFLAG_CLEAR;
@ -13195,6 +13257,7 @@ static void m68k_op_divu_16_aw(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return; return;
} }
USE_CYCLES(10);
FLAG_V = VFLAG_SET; FLAG_V = VFLAG_SET;
return; return;
} }
@ -13214,6 +13277,9 @@ static void m68k_op_divu_16_al(void)
if(quotient < 0x10000) if(quotient < 0x10000)
{ {
int cyc = getDivu68kCycles(*r_dst,src);
USE_CYCLES(cyc);
FLAG_Z = quotient; FLAG_Z = quotient;
FLAG_N = NFLAG_16(quotient); FLAG_N = NFLAG_16(quotient);
FLAG_V = VFLAG_CLEAR; FLAG_V = VFLAG_CLEAR;
@ -13221,6 +13287,7 @@ static void m68k_op_divu_16_al(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return; return;
} }
USE_CYCLES(10);
FLAG_V = VFLAG_SET; FLAG_V = VFLAG_SET;
return; return;
} }
@ -13240,6 +13307,9 @@ static void m68k_op_divu_16_pcdi(void)
if(quotient < 0x10000) if(quotient < 0x10000)
{ {
int cyc = getDivu68kCycles(*r_dst,src);
USE_CYCLES(cyc);
FLAG_Z = quotient; FLAG_Z = quotient;
FLAG_N = NFLAG_16(quotient); FLAG_N = NFLAG_16(quotient);
FLAG_V = VFLAG_CLEAR; FLAG_V = VFLAG_CLEAR;
@ -13247,6 +13317,7 @@ static void m68k_op_divu_16_pcdi(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return; return;
} }
USE_CYCLES(10);
FLAG_V = VFLAG_SET; FLAG_V = VFLAG_SET;
return; return;
} }
@ -13266,6 +13337,9 @@ static void m68k_op_divu_16_pcix(void)
if(quotient < 0x10000) if(quotient < 0x10000)
{ {
int cyc = getDivu68kCycles(*r_dst,src);
USE_CYCLES(cyc);
FLAG_Z = quotient; FLAG_Z = quotient;
FLAG_N = NFLAG_16(quotient); FLAG_N = NFLAG_16(quotient);
FLAG_V = VFLAG_CLEAR; FLAG_V = VFLAG_CLEAR;
@ -13273,6 +13347,7 @@ static void m68k_op_divu_16_pcix(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return; return;
} }
USE_CYCLES(10);
FLAG_V = VFLAG_SET; FLAG_V = VFLAG_SET;
return; return;
} }
@ -13292,6 +13367,9 @@ static void m68k_op_divu_16_i(void)
if(quotient < 0x10000) if(quotient < 0x10000)
{ {
int cyc = getDivu68kCycles(*r_dst,src);
USE_CYCLES(cyc);
FLAG_Z = quotient; FLAG_Z = quotient;
FLAG_N = NFLAG_16(quotient); FLAG_N = NFLAG_16(quotient);
FLAG_V = VFLAG_CLEAR; FLAG_V = VFLAG_CLEAR;
@ -13299,6 +13377,7 @@ static void m68k_op_divu_16_i(void)
*r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
return; return;
} }
USE_CYCLES(10);
FLAG_V = VFLAG_SET; FLAG_V = VFLAG_SET;
return; return;
} }
@ -23951,7 +24030,11 @@ static void m68k_op_move16_32(void)
static void m68k_op_muls_16_d(void) static void m68k_op_muls_16_d(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(DY) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); uint src = MAKE_INT_16(DY);
uint res = MASK_OUT_ABOVE_32( src * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst)));
uint cyc = getMuls68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -23965,7 +24048,11 @@ static void m68k_op_muls_16_d(void)
static void m68k_op_muls_16_ai(void) static void m68k_op_muls_16_ai(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AY_AI_16()) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); uint src = MAKE_INT_16(OPER_AY_AI_16());
uint res = MASK_OUT_ABOVE_32( src * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst)));
uint cyc = getMuls68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -23979,7 +24066,11 @@ static void m68k_op_muls_16_ai(void)
static void m68k_op_muls_16_pi(void) static void m68k_op_muls_16_pi(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AY_PI_16()) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); uint src = MAKE_INT_16(OPER_AY_PI_16());
uint res = MASK_OUT_ABOVE_32( src * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst)));
uint cyc = getMuls68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -23993,7 +24084,11 @@ static void m68k_op_muls_16_pi(void)
static void m68k_op_muls_16_pd(void) static void m68k_op_muls_16_pd(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AY_PD_16()) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); uint src = MAKE_INT_16(OPER_AY_PD_16());
uint res = MASK_OUT_ABOVE_32( src * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst)));
uint cyc = getMuls68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24007,7 +24102,11 @@ static void m68k_op_muls_16_pd(void)
static void m68k_op_muls_16_di(void) static void m68k_op_muls_16_di(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AY_DI_16()) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); uint src = MAKE_INT_16(OPER_AY_DI_16());
uint res = MASK_OUT_ABOVE_32( src * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst)));
uint cyc = getMuls68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24021,7 +24120,11 @@ static void m68k_op_muls_16_di(void)
static void m68k_op_muls_16_ix(void) static void m68k_op_muls_16_ix(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AY_IX_16()) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); uint src = MAKE_INT_16(OPER_AY_IX_16());
uint res = MASK_OUT_ABOVE_32( src * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst)));
uint cyc = getMuls68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24035,7 +24138,11 @@ static void m68k_op_muls_16_ix(void)
static void m68k_op_muls_16_aw(void) static void m68k_op_muls_16_aw(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AW_16()) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); uint src = MAKE_INT_16(OPER_AW_16());
uint res = MASK_OUT_ABOVE_32( src * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst)));
uint cyc = getMuls68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24049,7 +24156,11 @@ static void m68k_op_muls_16_aw(void)
static void m68k_op_muls_16_al(void) static void m68k_op_muls_16_al(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_AL_16()) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); uint src = MAKE_INT_16(OPER_AL_16());
uint res = MASK_OUT_ABOVE_32( src * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst)));
uint cyc = getMuls68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24063,7 +24174,11 @@ static void m68k_op_muls_16_al(void)
static void m68k_op_muls_16_pcdi(void) static void m68k_op_muls_16_pcdi(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_PCDI_16()) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); uint src = MAKE_INT_16(OPER_PCDI_16());
uint res = MASK_OUT_ABOVE_32( src * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst)));
uint cyc = getMuls68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24077,7 +24192,11 @@ static void m68k_op_muls_16_pcdi(void)
static void m68k_op_muls_16_pcix(void) static void m68k_op_muls_16_pcix(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_PCIX_16()) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); uint src = MAKE_INT_16(OPER_PCIX_16());
uint res = MASK_OUT_ABOVE_32( src * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst)));
uint cyc = getMuls68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24091,7 +24210,11 @@ static void m68k_op_muls_16_pcix(void)
static void m68k_op_muls_16_i(void) static void m68k_op_muls_16_i(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(OPER_I_16()) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); uint src = MAKE_INT_16(OPER_I_16());
uint res = MASK_OUT_ABOVE_32( src * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst)));
uint cyc = getMuls68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24105,7 +24228,11 @@ static void m68k_op_muls_16_i(void)
static void m68k_op_mulu_16_d(void) static void m68k_op_mulu_16_d(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = MASK_OUT_ABOVE_16(DY) * MASK_OUT_ABOVE_16(*r_dst); uint src = MASK_OUT_ABOVE_16(DY);
uint res = src * MASK_OUT_ABOVE_16(*r_dst);
uint cyc = getMulu68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24119,7 +24246,11 @@ static void m68k_op_mulu_16_d(void)
static void m68k_op_mulu_16_ai(void) static void m68k_op_mulu_16_ai(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = OPER_AY_AI_16() * MASK_OUT_ABOVE_16(*r_dst); uint src = OPER_AY_AI_16();
uint res = src * MASK_OUT_ABOVE_16(*r_dst);
uint cyc = getMulu68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24133,7 +24264,11 @@ static void m68k_op_mulu_16_ai(void)
static void m68k_op_mulu_16_pi(void) static void m68k_op_mulu_16_pi(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = OPER_AY_PI_16() * MASK_OUT_ABOVE_16(*r_dst); uint src = OPER_AY_PI_16();
uint res = src * MASK_OUT_ABOVE_16(*r_dst);
uint cyc = getMulu68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24147,7 +24282,11 @@ static void m68k_op_mulu_16_pi(void)
static void m68k_op_mulu_16_pd(void) static void m68k_op_mulu_16_pd(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = OPER_AY_PD_16() * MASK_OUT_ABOVE_16(*r_dst); uint src = OPER_AY_PD_16();
uint res = src * MASK_OUT_ABOVE_16(*r_dst);
uint cyc = getMulu68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24161,7 +24300,11 @@ static void m68k_op_mulu_16_pd(void)
static void m68k_op_mulu_16_di(void) static void m68k_op_mulu_16_di(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = OPER_AY_DI_16() * MASK_OUT_ABOVE_16(*r_dst); uint src = OPER_AY_DI_16();
uint res = src * MASK_OUT_ABOVE_16(*r_dst);
uint cyc = getMulu68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24175,7 +24318,11 @@ static void m68k_op_mulu_16_di(void)
static void m68k_op_mulu_16_ix(void) static void m68k_op_mulu_16_ix(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = OPER_AY_IX_16() * MASK_OUT_ABOVE_16(*r_dst); uint src = OPER_AY_IX_16();
uint res = src * MASK_OUT_ABOVE_16(*r_dst);
uint cyc = getMulu68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24189,7 +24336,11 @@ static void m68k_op_mulu_16_ix(void)
static void m68k_op_mulu_16_aw(void) static void m68k_op_mulu_16_aw(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = OPER_AW_16() * MASK_OUT_ABOVE_16(*r_dst); uint src = OPER_AW_16();
uint res = src * MASK_OUT_ABOVE_16(*r_dst);
uint cyc = getMulu68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24203,7 +24354,11 @@ static void m68k_op_mulu_16_aw(void)
static void m68k_op_mulu_16_al(void) static void m68k_op_mulu_16_al(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = OPER_AL_16() * MASK_OUT_ABOVE_16(*r_dst); uint src = OPER_AL_16();
uint res = src * MASK_OUT_ABOVE_16(*r_dst);
uint cyc = getMulu68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24217,7 +24372,11 @@ static void m68k_op_mulu_16_al(void)
static void m68k_op_mulu_16_pcdi(void) static void m68k_op_mulu_16_pcdi(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = OPER_PCDI_16() * MASK_OUT_ABOVE_16(*r_dst); uint src = OPER_PCDI_16();
uint res = src * MASK_OUT_ABOVE_16(*r_dst);
uint cyc = getMulu68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24231,7 +24390,11 @@ static void m68k_op_mulu_16_pcdi(void)
static void m68k_op_mulu_16_pcix(void) static void m68k_op_mulu_16_pcix(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = OPER_PCIX_16() * MASK_OUT_ABOVE_16(*r_dst); uint src = OPER_PCIX_16();
uint res = src * MASK_OUT_ABOVE_16(*r_dst);
uint cyc = getMulu68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -24245,7 +24408,11 @@ static void m68k_op_mulu_16_pcix(void)
static void m68k_op_mulu_16_i(void) static void m68k_op_mulu_16_i(void)
{ {
uint* r_dst = &DX; uint* r_dst = &DX;
uint res = OPER_I_16() * MASK_OUT_ABOVE_16(*r_dst); uint src = OPER_I_16();
uint res = src * MASK_OUT_ABOVE_16(*r_dst);
uint cyc = getMulu68kCycles(src);
USE_CYCLES(cyc);
*r_dst = res; *r_dst = res;
@ -34869,12 +35036,12 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_or_32_er_pd , 0xf1f8, 0x80a0, { 16, 16, 7, 7}}, {m68k_op_or_32_er_pd , 0xf1f8, 0x80a0, { 16, 16, 7, 7}},
{m68k_op_or_32_er_di , 0xf1f8, 0x80a8, { 18, 18, 7, 7}}, {m68k_op_or_32_er_di , 0xf1f8, 0x80a8, { 18, 18, 7, 7}},
{m68k_op_or_32_er_ix , 0xf1f8, 0x80b0, { 20, 20, 9, 9}}, {m68k_op_or_32_er_ix , 0xf1f8, 0x80b0, { 20, 20, 9, 9}},
{m68k_op_divu_16_d , 0xf1f8, 0x80c0, {140, 108, 44, 44}}, {m68k_op_divu_16_d , 0xf1f8, 0x80c0, { 0, 108, 44, 44}},
{m68k_op_divu_16_ai , 0xf1f8, 0x80d0, {144, 112, 48, 48}}, {m68k_op_divu_16_ai , 0xf1f8, 0x80d0, { 4, 112, 48, 48}},
{m68k_op_divu_16_pi , 0xf1f8, 0x80d8, {144, 112, 48, 48}}, {m68k_op_divu_16_pi , 0xf1f8, 0x80d8, { 4, 112, 48, 48}},
{m68k_op_divu_16_pd , 0xf1f8, 0x80e0, {146, 114, 49, 49}}, {m68k_op_divu_16_pd , 0xf1f8, 0x80e0, { 6, 114, 49, 49}},
{m68k_op_divu_16_di , 0xf1f8, 0x80e8, {148, 116, 49, 49}}, {m68k_op_divu_16_di , 0xf1f8, 0x80e8, { 8, 116, 49, 49}},
{m68k_op_divu_16_ix , 0xf1f8, 0x80f0, {150, 118, 51, 51}}, {m68k_op_divu_16_ix , 0xf1f8, 0x80f0, { 10, 118, 51, 51}},
{m68k_op_sbcd_8_rr , 0xf1f8, 0x8100, { 6, 6, 4, 4}}, {m68k_op_sbcd_8_rr , 0xf1f8, 0x8100, { 6, 6, 4, 4}},
{m68k_op_sbcd_8_mm , 0xf1f8, 0x8108, { 18, 18, 16, 16}}, {m68k_op_sbcd_8_mm , 0xf1f8, 0x8108, { 18, 18, 16, 16}},
{m68k_op_or_8_re_ai , 0xf1f8, 0x8110, { 12, 12, 8, 8}}, {m68k_op_or_8_re_ai , 0xf1f8, 0x8110, { 12, 12, 8, 8}},
@ -34896,12 +35063,12 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_or_32_re_pd , 0xf1f8, 0x81a0, { 22, 22, 9, 9}}, {m68k_op_or_32_re_pd , 0xf1f8, 0x81a0, { 22, 22, 9, 9}},
{m68k_op_or_32_re_di , 0xf1f8, 0x81a8, { 24, 24, 9, 9}}, {m68k_op_or_32_re_di , 0xf1f8, 0x81a8, { 24, 24, 9, 9}},
{m68k_op_or_32_re_ix , 0xf1f8, 0x81b0, { 26, 26, 11, 11}}, {m68k_op_or_32_re_ix , 0xf1f8, 0x81b0, { 26, 26, 11, 11}},
{m68k_op_divs_16_d , 0xf1f8, 0x81c0, {158, 122, 56, 56}}, {m68k_op_divs_16_d , 0xf1f8, 0x81c0, { 0, 122, 56, 56}},
{m68k_op_divs_16_ai , 0xf1f8, 0x81d0, {162, 126, 60, 60}}, {m68k_op_divs_16_ai , 0xf1f8, 0x81d0, { 4, 126, 60, 60}},
{m68k_op_divs_16_pi , 0xf1f8, 0x81d8, {162, 126, 60, 60}}, {m68k_op_divs_16_pi , 0xf1f8, 0x81d8, { 4, 126, 60, 60}},
{m68k_op_divs_16_pd , 0xf1f8, 0x81e0, {164, 128, 61, 61}}, {m68k_op_divs_16_pd , 0xf1f8, 0x81e0, { 6, 128, 61, 61}},
{m68k_op_divs_16_di , 0xf1f8, 0x81e8, {166, 130, 61, 61}}, {m68k_op_divs_16_di , 0xf1f8, 0x81e8, { 8, 130, 61, 61}},
{m68k_op_divs_16_ix , 0xf1f8, 0x81f0, {168, 132, 63, 63}}, {m68k_op_divs_16_ix , 0xf1f8, 0x81f0, { 10, 132, 63, 63}},
{m68k_op_sub_8_er_d , 0xf1f8, 0x9000, { 4, 4, 2, 2}}, {m68k_op_sub_8_er_d , 0xf1f8, 0x9000, { 4, 4, 2, 2}},
{m68k_op_sub_8_er_ai , 0xf1f8, 0x9010, { 8, 8, 6, 6}}, {m68k_op_sub_8_er_ai , 0xf1f8, 0x9010, { 8, 8, 6, 6}},
{m68k_op_sub_8_er_pi , 0xf1f8, 0x9018, { 8, 8, 6, 6}}, {m68k_op_sub_8_er_pi , 0xf1f8, 0x9018, { 8, 8, 6, 6}},
@ -35030,12 +35197,12 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_and_32_er_pd , 0xf1f8, 0xc0a0, { 16, 16, 7, 7}}, {m68k_op_and_32_er_pd , 0xf1f8, 0xc0a0, { 16, 16, 7, 7}},
{m68k_op_and_32_er_di , 0xf1f8, 0xc0a8, { 18, 18, 7, 7}}, {m68k_op_and_32_er_di , 0xf1f8, 0xc0a8, { 18, 18, 7, 7}},
{m68k_op_and_32_er_ix , 0xf1f8, 0xc0b0, { 20, 20, 9, 9}}, {m68k_op_and_32_er_ix , 0xf1f8, 0xc0b0, { 20, 20, 9, 9}},
{m68k_op_mulu_16_d , 0xf1f8, 0xc0c0, { 54, 30, 27, 27}}, {m68k_op_mulu_16_d , 0xf1f8, 0xc0c0, { 0, 30, 27, 27}},
{m68k_op_mulu_16_ai , 0xf1f8, 0xc0d0, { 58, 34, 31, 31}}, {m68k_op_mulu_16_ai , 0xf1f8, 0xc0d0, { 4, 34, 31, 31}},
{m68k_op_mulu_16_pi , 0xf1f8, 0xc0d8, { 58, 34, 31, 31}}, {m68k_op_mulu_16_pi , 0xf1f8, 0xc0d8, { 4, 34, 31, 31}},
{m68k_op_mulu_16_pd , 0xf1f8, 0xc0e0, { 60, 36, 32, 32}}, {m68k_op_mulu_16_pd , 0xf1f8, 0xc0e0, { 6, 36, 32, 32}},
{m68k_op_mulu_16_di , 0xf1f8, 0xc0e8, { 62, 38, 32, 32}}, {m68k_op_mulu_16_di , 0xf1f8, 0xc0e8, { 8, 38, 32, 32}},
{m68k_op_mulu_16_ix , 0xf1f8, 0xc0f0, { 64, 40, 34, 34}}, {m68k_op_mulu_16_ix , 0xf1f8, 0xc0f0, { 10, 40, 34, 34}},
{m68k_op_abcd_8_rr , 0xf1f8, 0xc100, { 6, 6, 4, 4}}, {m68k_op_abcd_8_rr , 0xf1f8, 0xc100, { 6, 6, 4, 4}},
{m68k_op_abcd_8_mm , 0xf1f8, 0xc108, { 18, 18, 16, 16}}, {m68k_op_abcd_8_mm , 0xf1f8, 0xc108, { 18, 18, 16, 16}},
{m68k_op_and_8_re_ai , 0xf1f8, 0xc110, { 12, 12, 8, 8}}, {m68k_op_and_8_re_ai , 0xf1f8, 0xc110, { 12, 12, 8, 8}},
@ -35056,12 +35223,12 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_and_32_re_pd , 0xf1f8, 0xc1a0, { 22, 22, 9, 9}}, {m68k_op_and_32_re_pd , 0xf1f8, 0xc1a0, { 22, 22, 9, 9}},
{m68k_op_and_32_re_di , 0xf1f8, 0xc1a8, { 24, 24, 9, 9}}, {m68k_op_and_32_re_di , 0xf1f8, 0xc1a8, { 24, 24, 9, 9}},
{m68k_op_and_32_re_ix , 0xf1f8, 0xc1b0, { 26, 26, 11, 11}}, {m68k_op_and_32_re_ix , 0xf1f8, 0xc1b0, { 26, 26, 11, 11}},
{m68k_op_muls_16_d , 0xf1f8, 0xc1c0, { 54, 32, 27, 27}}, {m68k_op_muls_16_d , 0xf1f8, 0xc1c0, { 0, 32, 27, 27}},
{m68k_op_muls_16_ai , 0xf1f8, 0xc1d0, { 58, 36, 31, 31}}, {m68k_op_muls_16_ai , 0xf1f8, 0xc1d0, { 4, 36, 31, 31}},
{m68k_op_muls_16_pi , 0xf1f8, 0xc1d8, { 58, 36, 31, 31}}, {m68k_op_muls_16_pi , 0xf1f8, 0xc1d8, { 4, 36, 31, 31}},
{m68k_op_muls_16_pd , 0xf1f8, 0xc1e0, { 60, 38, 32, 32}}, {m68k_op_muls_16_pd , 0xf1f8, 0xc1e0, { 6, 38, 32, 32}},
{m68k_op_muls_16_di , 0xf1f8, 0xc1e8, { 62, 40, 32, 32}}, {m68k_op_muls_16_di , 0xf1f8, 0xc1e8, { 8, 40, 32, 32}},
{m68k_op_muls_16_ix , 0xf1f8, 0xc1f0, { 64, 42, 34, 34}}, {m68k_op_muls_16_ix , 0xf1f8, 0xc1f0, { 10, 42, 34, 34}},
{m68k_op_add_8_er_d , 0xf1f8, 0xd000, { 4, 4, 2, 2}}, {m68k_op_add_8_er_d , 0xf1f8, 0xd000, { 4, 4, 2, 2}},
{m68k_op_add_8_er_ai , 0xf1f8, 0xd010, { 8, 8, 6, 6}}, {m68k_op_add_8_er_ai , 0xf1f8, 0xd010, { 8, 8, 6, 6}},
{m68k_op_add_8_er_pi , 0xf1f8, 0xd018, { 8, 8, 6, 6}}, {m68k_op_add_8_er_pi , 0xf1f8, 0xd018, { 8, 8, 6, 6}},
@ -35347,11 +35514,11 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_or_32_er_pcdi , 0xf1ff, 0x80ba, { 18, 18, 7, 7}}, {m68k_op_or_32_er_pcdi , 0xf1ff, 0x80ba, { 18, 18, 7, 7}},
{m68k_op_or_32_er_pcix , 0xf1ff, 0x80bb, { 20, 20, 9, 9}}, {m68k_op_or_32_er_pcix , 0xf1ff, 0x80bb, { 20, 20, 9, 9}},
{m68k_op_or_32_er_i , 0xf1ff, 0x80bc, { 16, 14, 6, 6}}, {m68k_op_or_32_er_i , 0xf1ff, 0x80bc, { 16, 14, 6, 6}},
{m68k_op_divu_16_aw , 0xf1ff, 0x80f8, {148, 116, 48, 48}}, {m68k_op_divu_16_aw , 0xf1ff, 0x80f8, { 8, 116, 48, 48}},
{m68k_op_divu_16_al , 0xf1ff, 0x80f9, {152, 120, 48, 48}}, {m68k_op_divu_16_al , 0xf1ff, 0x80f9, { 12, 120, 48, 48}},
{m68k_op_divu_16_pcdi , 0xf1ff, 0x80fa, {148, 116, 49, 49}}, {m68k_op_divu_16_pcdi , 0xf1ff, 0x80fa, { 8, 116, 49, 49}},
{m68k_op_divu_16_pcix , 0xf1ff, 0x80fb, {150, 118, 51, 51}}, {m68k_op_divu_16_pcix , 0xf1ff, 0x80fb, { 10, 118, 51, 51}},
{m68k_op_divu_16_i , 0xf1ff, 0x80fc, {144, 112, 46, 46}}, {m68k_op_divu_16_i , 0xf1ff, 0x80fc, { 4, 112, 46, 46}},
{m68k_op_sbcd_8_mm_ay7 , 0xf1ff, 0x810f, { 18, 18, 16, 16}}, {m68k_op_sbcd_8_mm_ay7 , 0xf1ff, 0x810f, { 18, 18, 16, 16}},
{m68k_op_or_8_re_pi7 , 0xf1ff, 0x811f, { 12, 12, 8, 8}}, {m68k_op_or_8_re_pi7 , 0xf1ff, 0x811f, { 12, 12, 8, 8}},
{m68k_op_or_8_re_pd7 , 0xf1ff, 0x8127, { 14, 14, 9, 9}}, {m68k_op_or_8_re_pd7 , 0xf1ff, 0x8127, { 14, 14, 9, 9}},
@ -35363,11 +35530,11 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_unpk_16_mm_ay7 , 0xf1ff, 0x818f, { 0, 0, 13, 13}}, {m68k_op_unpk_16_mm_ay7 , 0xf1ff, 0x818f, { 0, 0, 13, 13}},
{m68k_op_or_32_re_aw , 0xf1ff, 0x81b8, { 24, 24, 8, 8}}, {m68k_op_or_32_re_aw , 0xf1ff, 0x81b8, { 24, 24, 8, 8}},
{m68k_op_or_32_re_al , 0xf1ff, 0x81b9, { 28, 28, 8, 8}}, {m68k_op_or_32_re_al , 0xf1ff, 0x81b9, { 28, 28, 8, 8}},
{m68k_op_divs_16_aw , 0xf1ff, 0x81f8, {166, 130, 60, 60}}, {m68k_op_divs_16_aw , 0xf1ff, 0x81f8, { 8, 130, 60, 60}},
{m68k_op_divs_16_al , 0xf1ff, 0x81f9, {170, 134, 60, 60}}, {m68k_op_divs_16_al , 0xf1ff, 0x81f9, { 12, 134, 60, 60}},
{m68k_op_divs_16_pcdi , 0xf1ff, 0x81fa, {166, 130, 61, 61}}, {m68k_op_divs_16_pcdi , 0xf1ff, 0x81fa, { 8, 130, 61, 61}},
{m68k_op_divs_16_pcix , 0xf1ff, 0x81fb, {168, 132, 63, 63}}, {m68k_op_divs_16_pcix , 0xf1ff, 0x81fb, { 10, 132, 63, 63}},
{m68k_op_divs_16_i , 0xf1ff, 0x81fc, {162, 126, 58, 58}}, {m68k_op_divs_16_i , 0xf1ff, 0x81fc, { 4, 126, 58, 58}},
{m68k_op_sub_8_er_pi7 , 0xf1ff, 0x901f, { 8, 8, 6, 6}}, {m68k_op_sub_8_er_pi7 , 0xf1ff, 0x901f, { 8, 8, 6, 6}},
{m68k_op_sub_8_er_pd7 , 0xf1ff, 0x9027, { 10, 10, 7, 7}}, {m68k_op_sub_8_er_pd7 , 0xf1ff, 0x9027, { 10, 10, 7, 7}},
{m68k_op_sub_8_er_aw , 0xf1ff, 0x9038, { 12, 12, 6, 6}}, {m68k_op_sub_8_er_aw , 0xf1ff, 0x9038, { 12, 12, 6, 6}},
@ -35457,11 +35624,11 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_and_32_er_pcdi , 0xf1ff, 0xc0ba, { 18, 18, 7, 7}}, {m68k_op_and_32_er_pcdi , 0xf1ff, 0xc0ba, { 18, 18, 7, 7}},
{m68k_op_and_32_er_pcix , 0xf1ff, 0xc0bb, { 20, 20, 9, 9}}, {m68k_op_and_32_er_pcix , 0xf1ff, 0xc0bb, { 20, 20, 9, 9}},
{m68k_op_and_32_er_i , 0xf1ff, 0xc0bc, { 16, 14, 6, 6}}, {m68k_op_and_32_er_i , 0xf1ff, 0xc0bc, { 16, 14, 6, 6}},
{m68k_op_mulu_16_aw , 0xf1ff, 0xc0f8, { 62, 38, 31, 31}}, {m68k_op_mulu_16_aw , 0xf1ff, 0xc0f8, { 8, 38, 31, 31}},
{m68k_op_mulu_16_al , 0xf1ff, 0xc0f9, { 66, 42, 31, 31}}, {m68k_op_mulu_16_al , 0xf1ff, 0xc0f9, { 12, 42, 31, 31}},
{m68k_op_mulu_16_pcdi , 0xf1ff, 0xc0fa, { 62, 38, 32, 32}}, {m68k_op_mulu_16_pcdi , 0xf1ff, 0xc0fa, { 8, 38, 32, 32}},
{m68k_op_mulu_16_pcix , 0xf1ff, 0xc0fb, { 64, 40, 34, 34}}, {m68k_op_mulu_16_pcix , 0xf1ff, 0xc0fb, { 10, 40, 34, 34}},
{m68k_op_mulu_16_i , 0xf1ff, 0xc0fc, { 58, 34, 29, 29}}, {m68k_op_mulu_16_i , 0xf1ff, 0xc0fc, { 4, 34, 29, 29}},
{m68k_op_abcd_8_mm_ay7 , 0xf1ff, 0xc10f, { 18, 18, 16, 16}}, {m68k_op_abcd_8_mm_ay7 , 0xf1ff, 0xc10f, { 18, 18, 16, 16}},
{m68k_op_and_8_re_pi7 , 0xf1ff, 0xc11f, { 12, 12, 8, 8}}, {m68k_op_and_8_re_pi7 , 0xf1ff, 0xc11f, { 12, 12, 8, 8}},
{m68k_op_and_8_re_pd7 , 0xf1ff, 0xc127, { 14, 14, 9, 9}}, {m68k_op_and_8_re_pd7 , 0xf1ff, 0xc127, { 14, 14, 9, 9}},
@ -35471,11 +35638,11 @@ static const opcode_handler_struct m68k_opcode_handler_table[] =
{m68k_op_and_16_re_al , 0xf1ff, 0xc179, { 20, 20, 8, 8}}, {m68k_op_and_16_re_al , 0xf1ff, 0xc179, { 20, 20, 8, 8}},
{m68k_op_and_32_re_aw , 0xf1ff, 0xc1b8, { 24, 24, 8, 8}}, {m68k_op_and_32_re_aw , 0xf1ff, 0xc1b8, { 24, 24, 8, 8}},
{m68k_op_and_32_re_al , 0xf1ff, 0xc1b9, { 28, 28, 8, 8}}, {m68k_op_and_32_re_al , 0xf1ff, 0xc1b9, { 28, 28, 8, 8}},
{m68k_op_muls_16_aw , 0xf1ff, 0xc1f8, { 62, 40, 31, 31}}, {m68k_op_muls_16_aw , 0xf1ff, 0xc1f8, { 8, 40, 31, 31}},
{m68k_op_muls_16_al , 0xf1ff, 0xc1f9, { 66, 44, 31, 31}}, {m68k_op_muls_16_al , 0xf1ff, 0xc1f9, { 12, 44, 31, 31}},
{m68k_op_muls_16_pcdi , 0xf1ff, 0xc1fa, { 62, 40, 32, 32}}, {m68k_op_muls_16_pcdi , 0xf1ff, 0xc1fa, { 8, 40, 32, 32}},
{m68k_op_muls_16_pcix , 0xf1ff, 0xc1fb, { 64, 42, 34, 34}}, {m68k_op_muls_16_pcix , 0xf1ff, 0xc1fb, { 10, 42, 34, 34}},
{m68k_op_muls_16_i , 0xf1ff, 0xc1fc, { 58, 36, 29, 29}}, {m68k_op_muls_16_i , 0xf1ff, 0xc1fc, { 4, 36, 29, 29}},
{m68k_op_add_8_er_pi7 , 0xf1ff, 0xd01f, { 8, 8, 6, 6}}, {m68k_op_add_8_er_pi7 , 0xf1ff, 0xd01f, { 8, 8, 6, 6}},
{m68k_op_add_8_er_pd7 , 0xf1ff, 0xd027, { 10, 10, 7, 7}}, {m68k_op_add_8_er_pd7 , 0xf1ff, 0xd027, { 10, 10, 7, 7}},
{m68k_op_add_8_er_aw , 0xf1ff, 0xd038, { 12, 12, 6, 6}}, {m68k_op_add_8_er_aw , 0xf1ff, 0xd038, { 12, 12, 6, 6}},

View File

@ -30,7 +30,6 @@
** - implemented correct SSG-EG emulation (Asterix, Beavis&Butthead, Bubba'n Six & many others) ** - implemented correct SSG-EG emulation (Asterix, Beavis&Butthead, Bubba'n Six & many others)
** - adjusted some EG rates ** - adjusted some EG rates
** - modified address/data port behavior ** - modified address/data port behavior
** - fixed Phase Modulation (LFO) calculations (precision reduced to 11 bits)
** **
** TODO: complete SSG-EG documentation ** TODO: complete SSG-EG documentation
** **
@ -584,8 +583,9 @@ typedef struct
UINT32 eg_timer_add; /* step of eg_timer */ UINT32 eg_timer_add; /* step of eg_timer */
UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 3 samples (on real chip) */ UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 3 samples (on real chip) */
/* there are 2048 FNUMs that can be generated using FNUM/BLK registers */ /* there are 2048 FNUMs that can be generated using FNUM/BLK registers
UINT32 fn_table[2048]; /* fnumber->increment counter */ but LFO works with one more bit of a precision so we really need 4096 elements */
UINT32 fn_table[4096]; /* fnumber->increment counter */
UINT32 fn_max; /* max increment (required for calculating phase overflow) */ UINT32 fn_max; /* max increment (required for calculating phase overflow) */
/* LFO */ /* LFO */
@ -1236,21 +1236,18 @@ INLINE void update_ssg_eg_channel(FM_SLOT *SLOT)
INLINE void update_phase_lfo_slot(FM_SLOT *SLOT , INT32 pms, UINT32 block_fnum) INLINE void update_phase_lfo_slot(FM_SLOT *SLOT , INT32 pms, UINT32 block_fnum)
{ {
UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8; UINT32 fnum_lfo = (block_fnum & 0x7f0) << 4; /* ((block_fnum & 0x7f0) >> 4) * 32 * 8; */
INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + pms + LFO_PM ]; INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + pms + LFO_PM ];
if (lfo_fn_table_index_offset) /* LFO phase modulation active */ if (lfo_fn_table_index_offset) /* LFO phase modulation active */
{ {
/* retrieve BLOCK register value */
UINT8 blk = (block_fnum >> 11) & 7; UINT8 blk = (block_fnum >> 11) & 7;
UINT32 fn = (block_fnum*2 + (UINT32)lfo_fn_table_index_offset) & 0xfff;
/* apply phase modulation to FNUM register value */ /* keyscale code */
UINT32 fn = (block_fnum + (UINT32)lfo_fn_table_index_offset) & 0x7ff; int kc = (blk<<2) | opn_fktable[fn >> 8];
/* recalculate keyscale code */ /* (frequency) phase increment counter */
int kc = (blk<<2) | opn_fktable[fn >> 7];
/* recalculate (frequency) phase increment counter */
int fc = (ym2612.OPN.fn_table[fn]>>(7-blk)) + SLOT->DT[kc]; int fc = (ym2612.OPN.fn_table[fn]>>(7-blk)) + SLOT->DT[kc];
/* (frequency) phase overflow (credits to Nemesis) */ /* (frequency) phase overflow (credits to Nemesis) */
@ -1268,22 +1265,19 @@ INLINE void update_phase_lfo_slot(FM_SLOT *SLOT , INT32 pms, UINT32 block_fnum)
INLINE void update_phase_lfo_channel(FM_CH *CH) INLINE void update_phase_lfo_channel(FM_CH *CH)
{ {
UINT32 block_fnum = CH->block_fnum; UINT32 block_fnum = CH->block_fnum;
UINT32 fnum_lfo = (block_fnum & 0x7f0) << 4; /* ((block_fnum & 0x7f0) >> 4) * 32 * 8; */
UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8;
INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + CH->pms + LFO_PM ]; INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + CH->pms + LFO_PM ];
if (lfo_fn_table_index_offset) /* LFO phase modulation active */ if (lfo_fn_table_index_offset) /* LFO phase modulation active */
{ {
/* retrieve BLOCK register value */
UINT8 blk = (block_fnum >> 11) & 7; UINT8 blk = (block_fnum >> 11) & 7;
UINT32 fn = (block_fnum*2 + (UINT32)lfo_fn_table_index_offset) & 0xfff;
/* apply phase modulation to FNUM register value */ /* keyscale code */
UINT32 fn = (block_fnum + (UINT32)lfo_fn_table_index_offset) & 0x7ff; int kc = (blk<<2) | opn_fktable[fn >> 8];
/* recalculate keyscale code */ /* (frequency) phase increment counter */
int kc = (blk<<2) | opn_fktable[fn >> 7];
/* recalculate (frequency) phase increment counter */
int fc = (ym2612.OPN.fn_table[fn]>>(7-blk)); int fc = (ym2612.OPN.fn_table[fn]>>(7-blk));
/* (frequency) phase overflow (credits to Nemesis) */ /* (frequency) phase overflow (credits to Nemesis) */
@ -1319,6 +1313,7 @@ INLINE void chan_calc(FM_CH *CH)
UINT32 AM = LFO_AM >> CH->ams; UINT32 AM = LFO_AM >> CH->ams;
m2 = c1 = c2 = mem = 0; m2 = c1 = c2 = mem = 0;
*CH->mem_connect = CH->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */ *CH->mem_connect = CH->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
@ -1358,6 +1353,7 @@ INLINE void chan_calc(FM_CH *CH)
if( eg_out < ENV_QUIET ) /* SLOT 4 */ if( eg_out < ENV_QUIET ) /* SLOT 4 */
*CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, c2); *CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, c2);
/* store current MEM */ /* store current MEM */
CH->mem_value = mem; CH->mem_value = mem;
@ -1632,9 +1628,10 @@ static void OPNSetPres(int pres)
/* make time tables */ /* make time tables */
init_timetables(dt_tab); init_timetables(dt_tab);
/* there are 2048 FNUMs that can be generated using FNUM/BLK registers */ /* there are 2048 FNUMs that can be generated using FNUM/BLK registers
but LFO works with one more bit of a precision so we really need 4096 elements */
/* calculate fnumber -> increment counter table */ /* calculate fnumber -> increment counter table */
for(i = 0; i < 2048; i++) for(i = 0; i < 4096; i++)
{ {
/* freq table for octave 7 */ /* freq table for octave 7 */
/* OPN phase increment counter = 20bit */ /* OPN phase increment counter = 20bit */
@ -1642,7 +1639,7 @@ static void OPNSetPres(int pres)
/* where sample clock is M/144 */ /* where sample clock is M/144 */
/* this means the increment value for one clock sample is FNUM * 2^(B-1) = FNUM * 64 for octave 7 */ /* this means the increment value for one clock sample is FNUM * 2^(B-1) = FNUM * 64 for octave 7 */
/* we also need to handle the ratio between the chip frequency and the emulated frequency (can be 1.0) */ /* we also need to handle the ratio between the chip frequency and the emulated frequency (can be 1.0) */
ym2612.OPN.fn_table[i] = (UINT32)( (double)i * 64 * ym2612.OPN.ST.freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */ ym2612.OPN.fn_table[i] = (UINT32)( (double)i * 32 * ym2612.OPN.ST.freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
} }
/* maximal frequency is required for Phase overflow calculation, register size is 17 bits (Nemesis) */ /* maximal frequency is required for Phase overflow calculation, register size is 17 bits (Nemesis) */
@ -1847,7 +1844,7 @@ INLINE void OPNWriteReg(int r, int v)
/* keyscale code */ /* keyscale code */
CH->kcode = (blk<<2) | opn_fktable[fn >> 7]; CH->kcode = (blk<<2) | opn_fktable[fn >> 7];
/* phase increment counter */ /* phase increment counter */
CH->fc = ym2612.OPN.fn_table[fn]>>(7-blk); CH->fc = ym2612.OPN.fn_table[fn*2]>>(7-blk);
/* store fnum in clear form for LFO PM calculations */ /* store fnum in clear form for LFO PM calculations */
CH->block_fnum = (blk<<11) | fn; CH->block_fnum = (blk<<11) | fn;
@ -1866,7 +1863,7 @@ INLINE void OPNWriteReg(int r, int v)
/* keyscale code */ /* keyscale code */
ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7]; ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];
/* phase increment counter */ /* phase increment counter */
ym2612.OPN.SL3.fc[c] = ym2612.OPN.fn_table[fn]>>(7-blk); ym2612.OPN.SL3.fc[c] = ym2612.OPN.fn_table[fn*2]>>(7-blk);
ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn; //fn; ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn; //fn;
ym2612.CH[2].SLOT[SLOT1].Incr=-1; ym2612.CH[2].SLOT[SLOT1].Incr=-1;
} }

View File

@ -434,7 +434,7 @@ int system_frame (int do_skip)
/* 36 cycles latency after VINT occurence flag (Ex-Mutants, Tyrant) */ /* 36 cycles latency after VINT occurence flag (Ex-Mutants, Tyrant) */
m68k_run(line_m68k + 113); m68k_run(line_m68k + 113);
vint_pending = 1; vint_pending = 1;
if (reg[1] & 0x20) irq_status = (irq_status & ~0x40) | 0x16; if (reg[1] & 0x20) irq_status = (irq_status & ~0x40) | 0x36;
} }
else if (!do_skip) else if (!do_skip)
{ {

View File

@ -650,9 +650,8 @@ static inline void reg_w(unsigned int r, unsigned int d)
if (((d&0x10) != (reg[0]&0x10)) && hint_pending) if (((d&0x10) != (reg[0]&0x10)) && hint_pending)
{ {
/* update IRQ status */ /* update IRQ status */
irq_status &= 0x20; irq_status = 0x50;
irq_status |= 0x50; if (vint_pending && (reg[1] & 0x20)) irq_status |= 0x26;
if (vint_pending && (reg[1] & 0x20)) irq_status |= 6;
else if (d & 0x10) irq_status |= 4; else if (d & 0x10) irq_status |= 4;
} }
@ -676,9 +675,8 @@ static inline void reg_w(unsigned int r, unsigned int d)
if (((d&0x20) != (reg[1]&0x20)) && vint_pending) if (((d&0x20) != (reg[1]&0x20)) && vint_pending)
{ {
/* update IRQ status */ /* update IRQ status */
irq_status &= 0x20; irq_status = 0x50;
irq_status |= 0x50; if (d & 0x20) irq_status |= 0x26;
if (d & 0x20) irq_status |= 6;
else if (hint_pending && (reg[0] & 0x10)) irq_status |= 4; else if (hint_pending && (reg[0] & 0x10)) irq_status |= 4;
} }