pcsx2/x86/iHw.c
zerofrog df521ae24f 0.9.4 release
git-svn-id: http://pcsx2.googlecode.com/svn/branches/pcsx2_0.9.4@186 96395faa-99c1-11dd-bbfe-3dabce05a288
2007-11-11 02:55:00 +00:00

1297 lines
31 KiB
C

/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2007 Pcsx2 Team
*
* This program 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 program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
// stop compiling if NORECBUILD build (only for Visual Studio)
#if !(defined(_MSC_VER) && defined(PCSX2_NORECBUILD))
#include <string.h>
#include <malloc.h>
#include <assert.h>
#include "Common.h"
#include "iR5900.h"
#include "VUmicro.h"
#include "PsxMem.h"
#include "IPU/IPU.h"
#include "GS.h"
#ifndef PCSX2_VIRTUAL_MEM
extern u8 *psH; // hw mem
extern u16 *psHW;
extern u32 *psHL;
extern u64 *psHD;
#endif
extern int rdram_devices; // put 8 for TOOL and 2 for PS2 and PSX
extern int rdram_sdevid;
extern char sio_buffer[1024];
extern int sio_count;
int hwConstRead8(u32 x86reg, u32 mem, u32 sign)
{
#ifdef PCSX2_DEVBUILD
if( mem >= 0x10000000 && mem < 0x10008000 )
SysPrintf("hwRead8 to %x\n", mem);
#endif
if ((mem & 0xffffff0f) == 0x1000f200) {
if(mem == 0x1000f260) {
MMXONLY(if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf);
else)
XOR32RtoR(x86reg, x86reg);
return 0;
}
else if(mem == 0x1000F240) {
_eeReadConstMem8(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff], sign);
//psHu32(mem) &= ~0x4000;
return 0;
}
}
if (mem < 0x10010000)
{
_eeReadConstMem8(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff], sign);
}
else {
MMXONLY(if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf);
else )
XOR32RtoR(x86reg, x86reg);
}
return 0;
}
#define CONSTREAD16_CALL(name) { \
iFlushCall(0); \
CALLFunc((uptr)name); \
if( sign ) MOVSX32R16toR(EAX, EAX); \
else MOVZX32R16toR(EAX, EAX); \
} \
static u32 s_regreads[3] = {0x010200000, 0xbfff0000, 0xF0000102};
int hwConstRead16(u32 x86reg, u32 mem, u32 sign)
{
#ifdef PCSX2_DEVBUILD
if( mem >= 0x10002000 && mem < 0x10008000 )
SysPrintf("hwRead16 to %x\n", mem);
#endif
#ifdef PCSX2_DEVBUILD
if( mem >= 0x10000000 && mem < 0x10002000 ){
#ifdef EECNT_LOG
EECNT_LOG("cnt read to %x\n", mem);
#endif
}
#endif
switch (mem) {
case 0x10000000:
PUSH32I(0);
CONSTREAD16_CALL(rcntRcount);
ADD32ItoR(ESP, 4);
return 1;
case 0x10000010:
_eeReadConstMem16(x86reg, (uptr)&counters[0].mode, sign);
return 0;
case 0x10000020:
_eeReadConstMem16(x86reg, (uptr)&counters[0].mode, sign);
return 0;
case 0x10000030:
_eeReadConstMem16(x86reg, (uptr)&counters[0].hold, sign);
return 0;
case 0x10000800:
PUSH32I(1);
CONSTREAD16_CALL(rcntRcount);
ADD32ItoR(ESP, 4);
return 1;
case 0x10000810:
_eeReadConstMem16(x86reg, (uptr)&counters[1].mode, sign);
return 0;
case 0x10000820:
_eeReadConstMem16(x86reg, (uptr)&counters[1].target, sign);
return 0;
case 0x10000830:
_eeReadConstMem16(x86reg, (uptr)&counters[1].hold, sign);
return 0;
case 0x10001000:
PUSH32I(2);
CONSTREAD16_CALL(rcntRcount);
ADD32ItoR(ESP, 4);
return 1;
case 0x10001010:
_eeReadConstMem16(x86reg, (uptr)&counters[2].mode, sign);
return 0;
case 0x10001020:
_eeReadConstMem16(x86reg, (uptr)&counters[2].target, sign);
return 0;
case 0x10001800:
PUSH32I(3);
CONSTREAD16_CALL(rcntRcount);
ADD32ItoR(ESP, 4);
return 1;
case 0x10001810:
_eeReadConstMem16(x86reg, (uptr)&counters[3].mode, sign);
return 0;
case 0x10001820:
_eeReadConstMem16(x86reg, (uptr)&counters[3].target, sign);
return 0;
default:
if ((mem & 0xffffff0f) == 0x1000f200) {
if(mem == 0x1000f260) {
MMXONLY(if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf);
else )
XOR32RtoR(x86reg, x86reg);
return 0;
}
else if(mem == 0x1000F240) {
MMXONLY(if( IS_MMXREG(x86reg) ) {
MOVDMtoMMX(x86reg&0xf, (uptr)&PS2MEM_HW[(mem) & 0xffff] - 2);
PORMtoR(x86reg&0xf, (uptr)&s_regreads[0]);
PANDMtoR(x86reg&0xf, (uptr)&s_regreads[1]);
}
else )
{
if( sign ) MOVSX32M16toR(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff]);
else MOVZX32M16toR(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff]);
OR32ItoR(x86reg, 0x0102);
AND32ItoR(x86reg, ~0x4000);
}
return 0;
}
}
if (mem < 0x10010000) {
_eeReadConstMem16(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff], sign);
}
else {
MMXONLY(if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf);
else )
XOR32RtoR(x86reg, x86reg);
}
return 0;
}
}
#ifdef PCSX2_VIRTUAL_MEM
//
//#if defined(_MSC_VER) && !defined(__x86_64__)
//__declspec(naked) void recCheckF440()
//{
// __asm {
// add b440, 1
// mov eax, b440
// sub eax, 3
// mov edx, 31
//
// cmp eax, 27
// ja WriteVal
// shl eax, 2
// mov edx, dword ptr [eax+b440table]
//
//WriteVal:
// mov eax, PS2MEM_BASE_+0x1000f440
// mov dword ptr [eax], edx
// ret
// }
//}
//#else
//void recCheckF440();
//#endif
void iMemRead32Check()
{
// test if 0xf440
// if( bExecBIOS ) {
// u8* ptempptr[2];
// CMP32ItoR(ECX, 0x1000f440);
// ptempptr[0] = JNE8(0);
//
//// // increment and test
//// INC32M((uptr)&b440);
//// MOV32MtoR(EAX, (uptr)&b440);
//// SUB32ItoR(EAX, 3);
//// MOV32ItoR(EDX, 31);
////
//// CMP32ItoR(EAX, 27);
////
//// // look up table
//// ptempptr[1] = JA8(0);
//// SHL32ItoR(EAX, 2);
//// ADD32ItoR(EAX, (int)b440table);
//// MOV32RmtoR(EDX, EAX);
////
//// x86SetJ8( ptempptr[1] );
////
//// MOV32RtoM( (int)PS2MEM_HW+0xf440, EDX);
// CALLFunc((uptr)recCheckF440);
//
// x86SetJ8( ptempptr[0] );
// }
}
#endif
int hwContRead32_f440()
{
if ((psHu32(0xf430) >> 6) & 0xF)
return 0;
else
switch ((psHu32(0xf430)>>16) & 0xFFF){//MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5
case 0x21://INIT
{
int ret = 0x1F * (rdram_sdevid < rdram_devices);
rdram_sdevid += (rdram_sdevid < rdram_devices);
return ret;
}
case 0x23://CNFGA
return 0x0D0D; //PVER=3 | MVER=16 | DBL=1 | REFBIT=5
case 0x24://CNFGB
//0x0110 for PSX SVER=0 | CORG=8(5x9x7) | SPT=1 | DEVTYP=0 | BYTE=0
return 0x0090; //SVER=0 | CORG=4(5x9x6) | SPT=1 | DEVTYP=0 | BYTE=0
case 0x40://DEVID
return psHu32(0xf430) & 0x1F; // =SDEV
}
return 0;
}
int hwConstRead32(u32 x86reg, u32 mem)
{
//IPU regs
if ((mem>=0x10002000) && (mem<0x10003000)) {
return ipuConstRead32(x86reg, mem);
}
switch (mem) {
case 0x10000000:
iFlushCall(0);
PUSH32I(0);
CALLFunc((uptr)rcntRcount);
#ifdef EECNT_LOG
EECNT_LOG("Counter 0 count read = %x\n", rcntRcount(0));
#endif
ADD32ItoR(ESP, 4);
return 1;
case 0x10000010:
_eeReadConstMem32(x86reg, (uptr)&counters[0].mode);
#ifdef EECNT_LOG
EECNT_LOG("Counter 0 mode read = %x\n", counters[0].mode);
#endif
return 0;
case 0x10000020:
_eeReadConstMem32(x86reg, (uptr)&counters[0].target);
#ifdef EECNT_LOG
EECNT_LOG("Counter 0 target read = %x\n", counters[0].target);
#endif
return 0;
case 0x10000030:
_eeReadConstMem32(x86reg, (uptr)&counters[0].hold);
return 0;
case 0x10000800:
iFlushCall(0);
PUSH32I(1);
CALLFunc((uptr)rcntRcount);
#ifdef EECNT_LOG
EECNT_LOG("Counter 1 count read = %x\n", rcntRcount(1));
#endif
ADD32ItoR(ESP, 4);
return 1;
case 0x10000810:
_eeReadConstMem32(x86reg, (uptr)&counters[1].mode);
#ifdef EECNT_LOG
EECNT_LOG("Counter 1 mode read = %x\n", counters[1].mode);
#endif
return 0;
case 0x10000820:
_eeReadConstMem32(x86reg, (uptr)&counters[1].target);
#ifdef EECNT_LOG
EECNT_LOG("Counter 1 target read = %x\n", counters[1].target);
#endif
return 0;
case 0x10000830:
_eeReadConstMem32(x86reg, (uptr)&counters[1].hold);
return 0;
case 0x10001000:
iFlushCall(0);
PUSH32I(2);
CALLFunc((uptr)rcntRcount);
#ifdef EECNT_LOG
EECNT_LOG("Counter 2 count read = %x\n", rcntRcount(2));
#endif
ADD32ItoR(ESP, 4);
return 1;
case 0x10001010:
_eeReadConstMem32(x86reg, (uptr)&counters[2].mode);
#ifdef EECNT_LOG
EECNT_LOG("Counter 2 mode read = %x\n", counters[2].mode);
#endif
return 0;
case 0x10001020:
_eeReadConstMem32(x86reg, (uptr)&counters[2].target);
#ifdef EECNT_LOG
EECNT_LOG("Counter 2 target read = %x\n", counters[2].target);
#endif
return 0;
case 0x10001030:
_eeReadConstMem32(x86reg, (uptr)&counters[2].hold);
return 0;
case 0x10001800:
iFlushCall(0);
PUSH32I(3);
CALLFunc((uptr)rcntRcount);
#ifdef EECNT_LOG
EECNT_LOG("Counter 3 count read = %x\n", rcntRcount(3));
#endif
ADD32ItoR(ESP, 4);
return 1;
case 0x10001810:
_eeReadConstMem32(x86reg, (uptr)&counters[3].mode);
#ifdef EECNT_LOG
EECNT_LOG("Counter 3 mode read = %x\n", counters[3].mode);
#endif
return 0;
case 0x10001820:
_eeReadConstMem32(x86reg, (uptr)&counters[3].target);
#ifdef EECNT_LOG
EECNT_LOG("Counter 3 target read = %x\n", counters[3].target);
#endif
return 0;
case 0x10001830:
_eeReadConstMem32(x86reg, (uptr)&counters[3].hold);
return 0;
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf);
MMXONLY(else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf);)
else XOR32RtoR(x86reg, x86reg);
return 0;
case 0x1000f440:
iFlushCall(0);
CALLFunc((uptr)hwContRead32_f440);
return 1;
case 0x1000f520: // DMAC_ENABLER
_eeReadConstMem32(x86reg, (uptr)&PS2MEM_HW[0xf590]);
return 0;
default:
if ((mem & 0xffffff0f) == 0x1000f200) {
if(mem == 0x1000f260) {
if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf);
MMXONLY(else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf);)
else XOR32RtoR(x86reg, x86reg);
return 0;
}
else if(mem == 0x1000F240) {
if( IS_XMMREG(x86reg) ) {
SSEX_MOVD_M32_to_XMM(x86reg&0xf, (uptr)&PS2MEM_HW[(mem) & 0xffff]);
SSEX_POR_M128_to_XMM(x86reg&0xf, (uptr)&s_regreads[2]);
}
MMXONLY(else if( IS_MMXREG(x86reg) ) {
MOVDMtoMMX(x86reg&0xf, (uptr)&PS2MEM_HW[(mem) & 0xffff]);
PORMtoR(x86reg&0xf, (uptr)&s_regreads[2]);
})
else {
MOV32MtoR(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff]);
OR32ItoR(x86reg, 0xF0000102);
}
return 0;
}
}
if (mem < 0x10010000) {
_eeReadConstMem32(x86reg, (uptr)&PS2MEM_HW[(mem) & 0xffff]);
}
else {
if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf);
MMXONLY(else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf);)
else XOR32RtoR(x86reg, x86reg);
}
return 0;
}
}
void hwConstRead64(u32 mem, int mmreg) {
if ((mem>=0x10002000) && (mem<0x10003000)) {
ipuConstRead64(mem, mmreg);
return;
}
if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, (uptr)PSM(mem));
else {
X86_64ASSERT();
MMXONLY(MOVQMtoR(mmreg, (uptr)PSM(mem));
SetMMXstate();)
}
}
PCSX2_ALIGNED16(u32 s_TempFIFO[4]);
void hwConstRead128(u32 mem, int xmmreg) {
if (mem >= 0x10004000 && mem < 0x10008000) {
iFlushCall(0);
PUSH32I((uptr)&s_TempFIFO[0]);
PUSH32I(mem);
CALLFunc((uptr)ReadFIFO);
ADD32ItoR(ESP, 8);
_eeReadConstMem128( xmmreg, (uptr)&s_TempFIFO[0]);
return;
}
_eeReadConstMem128( xmmreg, (uptr)PSM(mem));
}
// when writing imm
#define recDmaExecI8(name, num) { \
MOV8ItoM((uptr)&PS2MEM_HW[(mem) & 0xffff], g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); \
if( g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 1 ) { \
TEST8ItoM((uptr)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \
j8Ptr[6] = JZ8(0); \
CALLFunc((uptr)dma##name); \
x86SetJ8( j8Ptr[6] ); \
} \
} \
#define recDmaExec8(name, num) { \
iFlushCall(0); \
if( IS_EECONSTREG(mmreg) ) { \
recDmaExecI8(name, num); \
} \
else { \
_eeMoveMMREGtoR(EAX, mmreg); \
_eeWriteConstMem8((uptr)&PS2MEM_HW[(mem) & 0xffff], mmreg); \
\
TEST8ItoR(EAX, 1); \
j8Ptr[5] = JZ8(0); \
TEST8ItoM((uptr)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \
j8Ptr[6] = JZ8(0); \
\
CALLFunc((uptr)dma##name); \
\
x86SetJ8( j8Ptr[5] ); \
x86SetJ8( j8Ptr[6] ); \
} \
} \
static void PrintDebug(u8 value)
{
if (value == '\n') {
sio_buffer[sio_count] = 0;
SysPrintf(COLOR_GREEN "%s\n" COLOR_RESET, sio_buffer);
sio_count = 0;
} else {
if (sio_count < 1023) {
sio_buffer[sio_count++] = value;
}
}
}
#define CONSTWRITE_CALLTIMER(name, index, bit) { \
if( !IS_EECONSTREG(mmreg) ) { \
if( bit == 8 ) MOVZX32R8toR(mmreg&0xf, mmreg&0xf); \
else if( bit == 16 ) MOVZX32R16toR(mmreg&0xf, mmreg&0xf); \
} \
_recPushReg(mmreg); \
iFlushCall(0); \
PUSH32I(index); \
CALLFunc((uptr)name); \
ADD32ItoR(ESP, 8); \
} \
#define CONSTWRITE_TIMERS(bit) \
case 0x10000000: CONSTWRITE_CALLTIMER(rcntWcount, 0, bit); break; \
case 0x10000010: CONSTWRITE_CALLTIMER(rcntWmode, 0, bit); break; \
case 0x10000020: CONSTWRITE_CALLTIMER(rcntWtarget, 0, bit); break; \
case 0x10000030: CONSTWRITE_CALLTIMER(rcntWhold, 0, bit); break; \
\
case 0x10000800: CONSTWRITE_CALLTIMER(rcntWcount, 1, bit); break; \
case 0x10000810: CONSTWRITE_CALLTIMER(rcntWmode, 1, bit); break; \
case 0x10000820: CONSTWRITE_CALLTIMER(rcntWtarget, 1, bit); break; \
case 0x10000830: CONSTWRITE_CALLTIMER(rcntWhold, 1, bit); break; \
\
case 0x10001000: CONSTWRITE_CALLTIMER(rcntWcount, 2, bit); break; \
case 0x10001010: CONSTWRITE_CALLTIMER(rcntWmode, 2, bit); break; \
case 0x10001020: CONSTWRITE_CALLTIMER(rcntWtarget, 2, bit); break; \
\
case 0x10001800: CONSTWRITE_CALLTIMER(rcntWcount, 3, bit); break; \
case 0x10001810: CONSTWRITE_CALLTIMER(rcntWmode, 3, bit); break; \
case 0x10001820: CONSTWRITE_CALLTIMER(rcntWtarget, 3, bit); break; \
void hwConstWrite8(u32 mem, int mmreg)
{
switch (mem) {
CONSTWRITE_TIMERS(8)
case 0x1000f180:
_recPushReg(mmreg); \
iFlushCall(0);
CALLFunc((uptr)PrintDebug);
ADD32ItoR(ESP, 4);
break;
case 0x10008001: // dma0 - vif0
recDmaExec8(VIF0, 0);
break;
case 0x10009001: // dma1 - vif1
recDmaExec8(VIF1, 1);
break;
case 0x1000a001: // dma2 - gif
recDmaExec8(GIF, 2);
break;
case 0x1000b001: // dma3 - fromIPU
recDmaExec8(IPU0, 3);
break;
case 0x1000b401: // dma4 - toIPU
recDmaExec8(IPU1, 4);
break;
case 0x1000c001: // dma5 - sif0
//if (value == 0) psxSu32(0x30) = 0x40000;
recDmaExec8(SIF0, 5);
break;
case 0x1000c401: // dma6 - sif1
recDmaExec8(SIF1, 6);
break;
case 0x1000c801: // dma7 - sif2
recDmaExec8(SIF2, 7);
break;
case 0x1000d001: // dma8 - fromSPR
recDmaExec8(SPR0, 8);
break;
case 0x1000d401: // dma9 - toSPR
recDmaExec8(SPR1, 9);
break;
case 0x1000f592: // DMAC_ENABLEW
_eeWriteConstMem8( (uptr)&PS2MEM_HW[0xf522], mmreg );
_eeWriteConstMem8( (uptr)&PS2MEM_HW[0xf592], mmreg );
break;
default:
if ((mem & 0xffffff0f) == 0x1000f200) {
u32 at = mem & 0xf0;
switch(at)
{
case 0x00:
_eeWriteConstMem8( (uptr)&PS2MEM_HW[mem&0xffff], mmreg);
break;
case 0x40:
if( IS_EECONSTREG(mmreg) ) {
if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) {
AND32ItoM( (uptr)&PS2MEM_HW[mem&0xfffc], ~0x100);
}
}
else {
_eeMoveMMREGtoR(EAX, mmreg);
TEST16ItoR(EAX, 0x100);
j8Ptr[5] = JNZ8(0);
AND32ItoM( (uptr)&PS2MEM_HW[mem&0xfffc], ~0x100);
x86SetJ8(j8Ptr[5]);
}
break;
}
return;
}
assert( (mem&0xff0f) != 0xf200 );
switch(mem&~3) {
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
default:
#ifdef PCSX2_VIRTUAL_MEM
//NOTE: this might cause crashes, but is more correct
_eeWriteConstMem8((u32)PS2MEM_BASE + mem, mmreg);
#else
if (mem < 0x10010000)
{
_eeWriteConstMem8((uptr)&PS2MEM_HW[mem&0xffff], mmreg);
}
#endif
}
break;
}
}
#define recDmaExecI16(name, num) { \
MOV16ItoM((uptr)&PS2MEM_HW[(mem) & 0xffff], g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); \
if( g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100 ) { \
TEST8ItoM((uptr)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \
j8Ptr[6] = JZ8(0); \
CALLFunc((uptr)dma##name); \
x86SetJ8( j8Ptr[6] ); \
} \
} \
#define recDmaExec16(name, num) { \
iFlushCall(0); \
if( IS_EECONSTREG(mmreg) ) { \
recDmaExecI16(name, num); \
} \
else { \
_eeMoveMMREGtoR(EAX, mmreg); \
_eeWriteConstMem16((uptr)&PS2MEM_HW[(mem) & 0xffff], mmreg); \
\
TEST16ItoR(EAX, 0x100); \
j8Ptr[5] = JZ8(0); \
TEST8ItoM((uptr)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \
j8Ptr[6] = JZ8(0); \
\
CALLFunc((uptr)dma##name); \
\
x86SetJ8( j8Ptr[5] ); \
x86SetJ8( j8Ptr[6] ); \
} \
} \
void hwConstWrite16(u32 mem, int mmreg)
{
switch(mem&~3) {
CONSTWRITE_TIMERS(16)
case 0x10008000: // dma0 - vif0
recDmaExec16(VIF0, 0);
break;
case 0x10009000: // dma1 - vif1 - chcr
recDmaExec16(VIF1, 1);
break;
case 0x1000a000: // dma2 - gif
recDmaExec16(GIF, 2);
break;
case 0x1000b000: // dma3 - fromIPU
recDmaExec16(IPU0, 3);
break;
case 0x1000b400: // dma4 - toIPU
recDmaExec16(IPU1, 4);
break;
case 0x1000c000: // dma5 - sif0
//if (value == 0) psxSu32(0x30) = 0x40000;
recDmaExec16(SIF0, 5);
break;
case 0x1000c002:
//?
break;
case 0x1000c400: // dma6 - sif1
recDmaExec16(SIF1, 6);
break;
case 0x1000c800: // dma7 - sif2
recDmaExec16(SIF2, 7);
break;
case 0x1000c802:
//?
break;
case 0x1000d000: // dma8 - fromSPR
recDmaExec16(SPR0, 8);
break;
case 0x1000d400: // dma9 - toSPR
recDmaExec16(SPR1, 9);
break;
case 0x1000f592: // DMAC_ENABLEW
_eeWriteConstMem16((uptr)&PS2MEM_HW[0xf522], mmreg);
_eeWriteConstMem16((uptr)&PS2MEM_HW[0xf592], mmreg);
break;
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
default:
if ((mem & 0xffffff0f) == 0x1000f200) {
u32 at = mem & 0xf0;
switch(at)
{
case 0x00:
_eeWriteConstMem16((uptr)&PS2MEM_HW[mem&0xffff], mmreg);
break;
case 0x20:
_eeWriteConstMem16OP((uptr)&PS2MEM_HW[mem&0xffff], mmreg, 1);
break;
case 0x30:
if( IS_EECONSTREG(mmreg) ) {
AND16ItoM((uptr)&PS2MEM_HW[mem&0xffff], ~g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]);
}
else {
NOT32R(mmreg&0xf);
AND16RtoM((uptr)&PS2MEM_HW[mem&0xffff], mmreg&0xf);
}
break;
case 0x40:
if( IS_EECONSTREG(mmreg) ) {
if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) {
AND16ItoM((uptr)&PS2MEM_HW[mem&0xffff], ~0x100);
}
else {
OR16ItoM((uptr)&PS2MEM_HW[mem&0xffff], 0x100);
}
}
else {
_eeMoveMMREGtoR(EAX, mmreg);
TEST16ItoR(EAX, 0x100);
j8Ptr[5] = JZ8(0);
OR16ItoM((uptr)&PS2MEM_HW[mem&0xffff], 0x100);
j8Ptr[6] = JMP8(0);
x86SetJ8( j8Ptr[5] );
AND16ItoM((uptr)&PS2MEM_HW[mem&0xffff], ~0x100);
x86SetJ8( j8Ptr[6] );
}
break;
case 0x60:
_eeWriteConstMem16((uptr)&PS2MEM_HW[mem&0xffff], 0);
break;
}
return;
}
#ifdef PCSX2_VIRTUAL_MEM
//NOTE: this might cause crashes, but is more correct
_eeWriteConstMem16((u32)PS2MEM_BASE + mem, mmreg);
#else
if (mem < 0x10010000)
{
_eeWriteConstMem16((uptr)&PS2MEM_HW[mem&0xffff], mmreg);
}
#endif
}
}
// when writing an Imm
#define recDmaExecI(name, num) { \
u32 c = g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]; \
/* Keep the old tag if in chain mode and hw doesnt set it*/ \
if( (c & 0xc) == 0x4 && (c&0xffff0000) == 0 ) { \
MOV16ItoM((uptr)&PS2MEM_HW[(mem) & 0xffff], c); \
} \
else MOV32ItoM((uptr)&PS2MEM_HW[(mem) & 0xffff], c); \
if( c & 0x100 ) { \
TEST8ItoM((uptr)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \
j8Ptr[6] = JZ8(0); \
CALLFunc((uptr)dma##name); \
x86SetJ8( j8Ptr[6] ); \
} \
} \
#define recDmaExec(name, num) { \
iFlushCall(0); \
if( IS_EECONSTREG(mmreg) ) { \
recDmaExecI(name, num); \
} \
else { \
_eeMoveMMREGtoR(EAX, mmreg); \
TEST32ItoR(EAX, 0xffff0000); \
j8Ptr[6] = JNZ8(0); \
MOV32RtoR(ECX, EAX); \
AND32ItoR(ECX, 0xc); \
CMP32ItoR(ECX, 4); \
j8Ptr[7] = JNE8(0); \
if( IS_XMMREG(mmreg) || IS_MMXREG(mmreg) ) { \
MOV16RtoM((uptr)&PS2MEM_HW[(mem) & 0xffff], EAX); \
} \
else { \
_eeWriteConstMem16((uptr)&PS2MEM_HW[(mem) & 0xffff], mmreg); \
} \
j8Ptr[8] = JMP8(0); \
x86SetJ8(j8Ptr[6]); \
x86SetJ8(j8Ptr[7]); \
_eeWriteConstMem32((uptr)&PS2MEM_HW[(mem) & 0xffff], mmreg); \
x86SetJ8(j8Ptr[8]); \
\
TEST16ItoR(EAX, 0x100); \
j8Ptr[5] = JZ8(0); \
TEST32ItoM((uptr)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \
j8Ptr[6] = JZ8(0); \
\
CALLFunc((uptr)dma##name); \
\
x86SetJ8( j8Ptr[5] ); \
x86SetJ8( j8Ptr[6] ); \
} \
} \
#define CONSTWRITE_CALLTIMER32(name, index, bit) { \
_recPushReg(mmreg); \
iFlushCall(0); \
PUSH32I(index); \
CALLFunc((uptr)name); \
ADD32ItoR(ESP, 8); \
} \
void hwConstWrite32(u32 mem, int mmreg)
{
//IPU regs
if ((mem>=0x10002000) && (mem<0x10003000)) {
//psHu32(mem) = value;
ipuConstWrite32(mem, mmreg);
return;
}
if ((mem>=0x10003800) && (mem<0x10003c00)) {
_recPushReg(mmreg);
iFlushCall(0);
PUSH32I(mem);
CALLFunc((uptr)vif0Write32);
ADD32ItoR(ESP, 8);
return;
}
if ((mem>=0x10003c00) && (mem<0x10004000)) {
_recPushReg(mmreg);
iFlushCall(0);
PUSH32I(mem);
CALLFunc((uptr)vif1Write32);
ADD32ItoR(ESP, 8);
return;
}
switch (mem) {
case 0x10000000: CONSTWRITE_CALLTIMER32(rcntWcount, 0, bit); break;
case 0x10000010: CONSTWRITE_CALLTIMER32(rcntWmode, 0, bit); break;
case 0x10000020: CONSTWRITE_CALLTIMER32(rcntWtarget, 0, bit); break;
case 0x10000030: CONSTWRITE_CALLTIMER32(rcntWhold, 0, bit); break;
case 0x10000800: CONSTWRITE_CALLTIMER32(rcntWcount, 1, bit); break;
case 0x10000810: CONSTWRITE_CALLTIMER32(rcntWmode, 1, bit); break;
case 0x10000820: CONSTWRITE_CALLTIMER32(rcntWtarget, 1, bit); break;
case 0x10000830: CONSTWRITE_CALLTIMER32(rcntWhold, 1, bit); break;
case 0x10001000: CONSTWRITE_CALLTIMER32(rcntWcount, 2, bit); break;
case 0x10001010: CONSTWRITE_CALLTIMER32(rcntWmode, 2, bit); break;
case 0x10001020: CONSTWRITE_CALLTIMER32(rcntWtarget, 2, bit); break;
case 0x10001800: CONSTWRITE_CALLTIMER32(rcntWcount, 3, bit); break;
case 0x10001810: CONSTWRITE_CALLTIMER32(rcntWmode, 3, bit); break;
case 0x10001820: CONSTWRITE_CALLTIMER32(rcntWtarget, 3, bit); break;
case GIF_CTRL:
_eeMoveMMREGtoR(EAX, mmreg);
iFlushCall(0);
TEST8ItoR(EAX, 1);
j8Ptr[5] = JZ8(0);
// reset GS
CALLFunc((uptr)gsGIFReset);
j8Ptr[6] = JMP8(0);
x86SetJ8( j8Ptr[5] );
AND32I8toR(EAX, 8);
MOV32RtoM((uptr)&PS2MEM_HW[mem&0xffff], EAX);
TEST16ItoR(EAX, 8);
j8Ptr[5] = JZ8(0);
OR8ItoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], 8);
j8Ptr[7] = JMP8(0);
x86SetJ8( j8Ptr[5] );
AND8ItoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], ~8);
x86SetJ8( j8Ptr[6] );
x86SetJ8( j8Ptr[7] );
return;
case GIF_MODE:
_eeMoveMMREGtoR(EAX, mmreg);
_eeWriteConstMem32((uptr)&PS2MEM_HW[mem&0xffff], mmreg);
AND8ItoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], ~5);
AND8ItoR(EAX, 5);
OR8RtoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], EAX);
return;
case GIF_STAT: // stat is readonly
return;
case 0x10008000: // dma0 - vif0
recDmaExec(VIF0, 0);
break;
case 0x10009000: // dma1 - vif1 - chcr
recDmaExec(VIF1, 1);
break;
case 0x1000a000: // dma2 - gif
recDmaExec(GIF, 2);
break;
case 0x1000b000: // dma3 - fromIPU
recDmaExec(IPU0, 3);
break;
case 0x1000b400: // dma4 - toIPU
recDmaExec(IPU1, 4);
break;
case 0x1000c000: // dma5 - sif0
//if (value == 0) psxSu32(0x30) = 0x40000;
recDmaExec(SIF0, 5);
break;
case 0x1000c400: // dma6 - sif1
recDmaExec(SIF1, 6);
break;
case 0x1000c800: // dma7 - sif2
recDmaExec(SIF2, 7);
break;
case 0x1000d000: // dma8 - fromSPR
recDmaExec(SPR0, 8);
break;
case 0x1000d400: // dma9 - toSPR
recDmaExec(SPR1, 9);
break;
case 0x1000e010: // DMAC_STAT
_eeMoveMMREGtoR(EAX, mmreg);
iFlushCall(0);
MOV32RtoR(ECX, EAX);
NOT32R(ECX);
AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX);
SHR32ItoR(EAX, 16);
XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX);
MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.n.Status.val);
AND32ItoR(EAX, 0x10807);
CMP32ItoR(EAX, 0x10801);
j8Ptr[5] = JNE8(0);
CALLFunc((uptr)cpuTestDMACInts);
x86SetJ8( j8Ptr[5] );
break;
case 0x1000f000: // INTC_STAT
_eeWriteConstMem32OP((uptr)&PS2MEM_HW[0xf000], mmreg, 2);
MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.n.Status.val);
AND32ItoR(EAX, 0x10407);
CMP32ItoR(EAX, 0x10401);
j8Ptr[5] = JNE8(0);
CALLFunc((uptr)cpuTestINTCInts);
x86SetJ8( j8Ptr[5] );
break;
case 0x1000f010: // INTC_MASK
_eeMoveMMREGtoR(EAX, mmreg);
iFlushCall(0);
XOR16RtoM((uptr)&PS2MEM_HW[0xf010], EAX);
MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.n.Status.val);
AND32ItoR(EAX, 0x10407);
CMP32ItoR(EAX, 0x10401);
j8Ptr[5] = JNE8(0);
CALLFunc((uptr)cpuTestINTCInts);
x86SetJ8( j8Ptr[5] );
break;
case 0x1000f130:
case 0x1000f410:
break;
case 0x1000f430://MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5
//if ((((value >> 16) & 0xFFF) == 0x21) && (((value >> 6) & 0xF) == 1) && (((psHu32(0xf440) >> 7) & 1) == 0))//INIT & SRP=0
// rdram_sdevid = 0
_eeMoveMMREGtoR(EAX, mmreg);
MOV32RtoR(EDX, EAX);
MOV32RtoR(ECX, EAX);
SHR32ItoR(EAX, 6);
SHR32ItoR(EDX, 16);
AND32ItoR(EAX, 0xf);
AND32ItoR(EDX, 0xfff);
CMP32ItoR(EAX, 1);
j8Ptr[5] = JNE8(0);
CMP32ItoR(EDX, 0x21);
j8Ptr[6] = JNE8(0);
TEST32ItoM((uptr)&psHu32(0xf440), 0x80);
j8Ptr[7] = JNZ8(0);
// if SIO repeater is cleared, reset sdevid
MOV32ItoM((uptr)&rdram_sdevid, 0);
//kill the busy bit
x86SetJ8(j8Ptr[5]);
x86SetJ8(j8Ptr[6]);
x86SetJ8(j8Ptr[7]);
AND32ItoR(ECX, ~0x80000000);
MOV32RtoM((uptr)&psHu32(0xf430), ECX);
break;
case 0x1000f440://MCH_DRD:
_eeWriteConstMem32((uptr)&PS2MEM_HW[0xf440], mmreg);
break;
case 0x1000f590: // DMAC_ENABLEW
_eeWriteConstMem32((uptr)&PS2MEM_HW[0xf520], mmreg);
_eeWriteConstMem32((uptr)&PS2MEM_HW[0xf590], mmreg);
return;
default:
if ((mem & 0xffffff0f) == 0x1000f200) {
u32 at = mem & 0xf0;
switch(at)
{
case 0x00:
_eeWriteConstMem32((uptr)&PS2MEM_HW[mem&0xffff], mmreg);
break;
case 0x20:
_eeWriteConstMem32OP((uptr)&PS2MEM_HW[mem&0xffff], mmreg, 1);
break;
case 0x30:
_eeWriteConstMem32OP((uptr)&PS2MEM_HW[mem&0xffff], mmreg, 2);
break;
case 0x40:
if( IS_EECONSTREG(mmreg) ) {
if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) {
AND32ItoM( (uptr)&PS2MEM_HW[mem&0xfffc], ~0x100);
}
else {
OR32ItoM((uptr)&PS2MEM_HW[mem&0xffff], 0x100);
}
}
else {
_eeMoveMMREGtoR(EAX, mmreg);
TEST32ItoR(EAX, 0x100);
j8Ptr[5] = JZ8(0);
OR32ItoM((uptr)&PS2MEM_HW[mem&0xffff], 0x100);
j8Ptr[6] = JMP8(0);
x86SetJ8( j8Ptr[5] );
AND32ItoM((uptr)&PS2MEM_HW[mem&0xffff], ~0x100);
x86SetJ8( j8Ptr[6] );
}
break;
case 0x60:
MOV32ItoM((uptr)&PS2MEM_HW[mem&0xffff], 0);
break;
}
return;
}
#ifdef PCSX2_VIRTUAL_MEM
//NOTE: this might cause crashes, but is more correct
_eeWriteConstMem32((u32)PS2MEM_BASE + mem, mmreg);
#else
if (mem < 0x10010000)
{
_eeWriteConstMem32((uptr)&PS2MEM_HW[mem&0xffff], mmreg);
}
#endif
break;
}
}
void hwConstWrite64(u32 mem, int mmreg)
{
if ((mem>=0x10002000) && (mem<=0x10002030)) {
ipuConstWrite64(mem, mmreg);
return;
}
if ((mem>=0x10003800) && (mem<0x10003c00)) {
_recPushReg(mmreg);
iFlushCall(0);
PUSH32I(mem);
CALLFunc((uptr)vif0Write32);
ADD32ItoR(ESP, 8);
return;
}
if ((mem>=0x10003c00) && (mem<0x10004000)) {
_recPushReg(mmreg);
iFlushCall(0);
PUSH32I(mem);
CALLFunc((uptr)vif1Write32);
ADD32ItoR(ESP, 8);
return;
}
switch (mem) {
case GIF_CTRL:
_eeMoveMMREGtoR(EAX, mmreg);
iFlushCall(0);
TEST8ItoR(EAX, 1);
j8Ptr[5] = JZ8(0);
// reset GS
CALLFunc((uptr)gsGIFReset);
j8Ptr[6] = JMP8(0);
x86SetJ8( j8Ptr[5] );
AND32I8toR(EAX, 8);
MOV32RtoM((uptr)&PS2MEM_HW[mem&0xffff], EAX);
TEST16ItoR(EAX, 8);
j8Ptr[5] = JZ8(0);
OR8ItoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], 8);
j8Ptr[7] = JMP8(0);
x86SetJ8( j8Ptr[5] );
AND8ItoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], ~8);
x86SetJ8( j8Ptr[6] );
x86SetJ8( j8Ptr[7] );
return;
case GIF_MODE:
_eeMoveMMREGtoR(EAX, mmreg);
_eeWriteConstMem32((uptr)&PS2MEM_HW[mem&0xffff], mmreg);
AND8ItoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], ~5);
AND8ItoR(EAX, 5);
OR8RtoM((uptr)&PS2MEM_HW[GIF_STAT&0xffff], EAX);
break;
case GIF_STAT: // stat is readonly
return;
case 0x1000a000: // dma2 - gif
recDmaExec(GIF, 2);
break;
case 0x1000e010: // DMAC_STAT
_eeMoveMMREGtoR(EAX, mmreg);
iFlushCall(0);
MOV32RtoR(ECX, EAX);
NOT32R(ECX);
AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX);
SHR32ItoR(EAX, 16);
XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX);
MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.n.Status.val);
AND32ItoR(EAX, 0x10807);
CMP32ItoR(EAX, 0x10801);
j8Ptr[5] = JNE8(0);
CALLFunc((uptr)cpuTestDMACInts);
x86SetJ8( j8Ptr[5] );
break;
case 0x1000f590: // DMAC_ENABLEW
_eeWriteConstMem32((uptr)&PS2MEM_HW[0xf520], mmreg);
_eeWriteConstMem32((uptr)&PS2MEM_HW[0xf590], mmreg);
break;
case 0x1000f000: // INTC_STAT
_eeWriteConstMem32OP((uptr)&PS2MEM_HW[mem&0xffff], mmreg, 2);
MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.n.Status.val);
AND32ItoR(EAX, 0x10407);
CMP32ItoR(EAX, 0x10401);
j8Ptr[5] = JNE8(0);
CALLFunc((uptr)cpuTestINTCInts);
x86SetJ8( j8Ptr[5] );
break;
case 0x1000f010: // INTC_MASK
_eeMoveMMREGtoR(EAX, mmreg);
iFlushCall(0);
XOR16RtoM((uptr)&PS2MEM_HW[0xf010], EAX);
MOV32MtoR(EAX, (uptr)&cpuRegs.CP0.n.Status.val);
AND32ItoR(EAX, 0x10407);
CMP32ItoR(EAX, 0x10401);
j8Ptr[5] = JNE8(0);
CALLFunc((uptr)cpuTestINTCInts);
x86SetJ8( j8Ptr[5] );
break;
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
default:
_eeWriteConstMem64((uptr)PSM(mem), mmreg);
break;
}
}
void hwConstWrite128(u32 mem, int mmreg)
{
if (mem >= 0x10004000 && mem < 0x10008000) {
_eeWriteConstMem128((uptr)&s_TempFIFO[0], mmreg);
iFlushCall(0);
PUSH32I((uptr)&s_TempFIFO[0]);
PUSH32I(mem);
CALLFunc((uptr)WriteFIFO);
ADD32ItoR(ESP, 8);
return;
}
switch (mem) {
case 0x1000f590: // DMAC_ENABLEW
_eeWriteConstMem32((uptr)&PS2MEM_HW[0xf520], mmreg);
_eeWriteConstMem32((uptr)&PS2MEM_HW[0xf590], mmreg);
break;
case 0x1000f130:
case 0x1000f410:
case 0x1000f430:
break;
default:
#ifdef PCSX2_VIRTUAL_MEM
_eeWriteConstMem128( PS2MEM_BASE_+mem, mmreg);
#else
if (mem < 0x10010000)
_eeWriteConstMem128((uptr)&PS2MEM_HW[mem&0xffff], mmreg);
#endif
break;
}
}
#endif // PCSX2_NORECBUILD