/* Pcsx2 - Pc Ps2 Emulator * Copyright (C) 2002-2003 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 */ #include #include #include "Common.h" #include "ir5900.h" #include "VUmicro.h" #include "PsxMem.h" #include "IPU.h" #include int hwInit() { #ifndef WIN32_VIRTUAL_MEM psH = (u8*)_aligned_malloc(0x00010000, 16); if (psH == NULL) { SysMessage(_("Error allocating memory")); return -1; } #endif gsInit(); vif0Init(); vif1Init(); vifDmaInit(); sifInit(); sprInit(); ipuInit(); return 0; } void hwShutdown() { #ifndef WIN32_VIRTUAL_MEM if (psH == NULL) return; _aligned_free(psH); psH = NULL; #endif ipuShutdown(); } void hwReset() { #ifdef WIN32_VIRTUAL_MEM memset(PS2MEM_HW+0x2000, 0, 0x0000e000); psHu32(0xf520) = 0x1201; psHu32(0xf260) = 0x1D000060; #else memset(psH, 0, 0x00010000); #endif // i guess this is kinda a version, it's used by some bioses psHu32(0xf590) = 0x1201; gsReset(); ipuReset(); } u8 hwRead8(u32 mem) { u8 ret; #ifdef PCSX2_DEVBUILD if( mem >= 0x10000000 && mem < 0x10008000 ) SysPrintf("hwRead8 to %x\n", mem); #endif #ifdef SPR_LOG SPR_LOG("Hardware read 8bit at %lx, ret %lx\n", mem, psHu8(mem)); #endif switch (mem) { default: if ((mem & 0xffffff0f) == 0x1000f200) { if(mem == 0x1000f260) ret = 0; else if(mem == 0x1000F240) { ret = psHu32(mem); //psHu32(mem) &= ~0x4000; } else ret = psHu32(mem); return (u8)ret; } if (mem < 0x10010000) { ret = psHu8(mem); } else ret = 0; #ifdef HW_LOG HW_LOG("Unknown Hardware Read 8 at %x\n",mem); #endif break; } return ret; } 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) { if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); else XOR32RtoR(x86reg, x86reg); return 0; } else if(mem == 0x1000F240) { _eeReadConstMem8(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff], sign); //psHu32(mem) &= ~0x4000; return 0; } } if (mem < 0x10010000) { _eeReadConstMem8(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff], sign); } else { if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); else XOR32RtoR(x86reg, x86reg); } return 0; } u16 hwRead16(u32 mem) { u16 ret; #ifdef PCSX2_DEVBUILD if( mem >= 0x10002000 && mem < 0x10008000 ) SysPrintf("hwRead16 to %x\n", mem); #endif #ifdef SPR_LOG SPR_LOG("Hardware read 16bit at %lx, ret %lx\n", mem, psHu16(mem)); #endif switch (mem) { case 0x10000000: ret = (u16)rcntRcount(0); break; case 0x10000010: ret = (u16)counters[0].mode; break; case 0x10000020: ret = (u16)counters[0].target; break; case 0x10000030: ret = (u16)counters[0].hold; break; case 0x10000800: ret = (u16)rcntRcount(1); break; case 0x10000810: ret = (u16)counters[1].mode; break; case 0x10000820: ret = (u16)counters[1].target; break; case 0x10000830: ret = (u16)counters[1].hold; break; case 0x10001000: ret = (u16)rcntRcount(2); break; case 0x10001010: ret = (u16)counters[2].mode; break; case 0x10001020: ret = (u16)counters[2].target; break; case 0x10001800: ret = (u16)rcntRcount(3); break; case 0x10001810: ret = (u16)counters[3].mode; break; case 0x10001820: ret = (u16)counters[3].target; break; default: if ((mem & 0xffffff0f) == 0x1000f200) { if(mem == 0x1000f260) ret = 0; else if(mem == 0x1000F240) { ret = psHu16(mem) | 0x0102; psHu32(mem) &= ~0x4000; } else ret = psHu32(mem); return (u16)ret; } if (mem < 0x10010000) { ret = psHu16(mem); } else ret = 0; #ifdef HW_LOG HW_LOG("Unknown Hardware Read 16 at %x\n",mem); #endif break; } return ret; } #define CONSTREAD16_CALL(name) { \ iFlushCall(0); \ CALLFunc((u32)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 switch (mem) { case 0x10000000: PUSH32I(0); CONSTREAD16_CALL(rcntRcount); ADD32ItoR(ESP, 4); return 1; case 0x10000010: _eeReadConstMem16(x86reg, (u32)&counters[0].mode, sign); return 0; case 0x10000020: _eeReadConstMem16(x86reg, (u32)&counters[0].mode, sign); return 0; case 0x10000030: _eeReadConstMem16(x86reg, (u32)&counters[0].hold, sign); return 0; case 0x10000800: PUSH32I(1); CONSTREAD16_CALL(rcntRcount); ADD32ItoR(ESP, 4); return 1; case 0x10000810: _eeReadConstMem16(x86reg, (u32)&counters[1].mode, sign); return 0; case 0x10000820: _eeReadConstMem16(x86reg, (u32)&counters[1].target, sign); return 0; case 0x10000830: _eeReadConstMem16(x86reg, (u32)&counters[1].hold, sign); return 0; case 0x10001000: PUSH32I(2); CONSTREAD16_CALL(rcntRcount); ADD32ItoR(ESP, 4); return 1; case 0x10001010: _eeReadConstMem16(x86reg, (u32)&counters[2].mode, sign); return 0; case 0x10001020: _eeReadConstMem16(x86reg, (u32)&counters[2].target, sign); return 0; case 0x10001800: PUSH32I(3); CONSTREAD16_CALL(rcntRcount); ADD32ItoR(ESP, 4); return 1; case 0x10001810: _eeReadConstMem16(x86reg, (u32)&counters[3].mode, sign); return 0; case 0x10001820: _eeReadConstMem16(x86reg, (u32)&counters[3].target, sign); return 0; default: if ((mem & 0xffffff0f) == 0x1000f200) { if(mem == 0x1000f260) { if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); else XOR32RtoR(x86reg, x86reg); return 0; } else if(mem == 0x1000F240) { if( IS_MMXREG(x86reg) ) { MOVDMtoMMX(x86reg&0xf, (u32)&PS2MEM_HW[(mem) & 0xffff] - 2); PORMtoR(x86reg&0xf, (u32)&s_regreads[0]); PANDMtoR(x86reg&0xf, (u32)&s_regreads[1]); } else { if( sign ) MOVSX32M16toR(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); else MOVZX32M16toR(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); OR32ItoR(x86reg, 0x0102); AND32ItoR(x86reg, ~0x4000); } return 0; } } if (mem < 0x10010000) { _eeReadConstMem16(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff], sign); } else { if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); else XOR32RtoR(x86reg, x86reg); } return 0; } } static int b440; extern BOOL bExecBIOS; static int b440table[] = { 0, 31, 31, 0, 31, 31, 0, 0, 31, 31, 0, 0, 31, 31, 0, 0, 31, 31, 0, 0, 31, 31, 0, 0, 31, 31, 0, 0 }; #ifdef WIN32_VIRTUAL_MEM __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 } } void iMemRead32Check() { // test if 0xf440 if( bExecBIOS ) { u8* ptempptr[2]; CMP32ItoR(ECX, 0x1000f440); ptempptr[0] = JNE8(0); // // increment and test // INC32M((int)&b440); // MOV32MtoR(EAX, (int)&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((u32)recCheckF440); x86SetJ8( ptempptr[0] ); } } #endif u32 hwRead32(u32 mem) { u32 ret; #ifdef SPR_LOG SPR_LOG("Hardware read 32bit at %lx, ret %lx\n", mem, psHu32(mem)); #endif //IPU regs if ((mem>=0x10002000) && (mem<0x10003000)) { return ipuRead32(mem); } // gauntlen uses 0x1001xxxx switch (mem) { case 0x10000000: return (u16)rcntRcount(0); case 0x10000010: return (u16)counters[0].mode; case 0x10000020: return (u16)counters[0].target; case 0x10000030: return (u16)counters[0].hold; case 0x10000800: return (u16)rcntRcount(1); case 0x10000810: return (u16)counters[1].mode; case 0x10000820: return (u16)counters[1].target; case 0x10000830: return (u16)counters[1].hold; case 0x10001000: return (u16)rcntRcount(2); case 0x10001010: return (u16)counters[2].mode; case 0x10001020: return (u16)counters[2].target; case 0x10001800: return (u16)rcntRcount(3); case 0x10001810: return (u16)counters[3].mode; case 0x10001820: return (u16)counters[3].target; #ifdef PCSX2_DEVBUILD case 0x1000A000: ret = psHu32(mem);//dma2 chcr HW_LOG("Hardware read DMA2_CHCR 32bit at %lx, ret %lx\n", mem, ret); break; case 0x1000A010: ret = psHu32(mem);//dma2 madr HW_LOG("Hardware read DMA2_MADR 32bit at %lx, ret %lx\n", mem, ret); break; case 0x1000A020: ret = psHu32(mem);//dma2 qwc HW_LOG("Hardware readDMA2_QWC 32bit at %lx, ret %lx\n", mem, ret); break; case 0x1000A030: ret = psHu32(mem);//dma2 taddr HW_LOG("Hardware read DMA2_TADDR 32bit at %lx, ret %lx\n", mem, ret); break; case 0x1000A040: ret = psHu32(mem);//dma2 asr0 HW_LOG("Hardware read DMA2_ASR0 32bit at %lx, ret %lx\n", mem, ret); break; case 0x1000A050: ret = psHu32(mem);//dma2 asr1 HW_LOG("Hardware read DMA2_ASR1 32bit at %lx, ret %lx\n", mem, ret); break; case 0x1000A080: ret = psHu32(mem);//dma2 saddr HW_LOG("Hardware read DMA2_SADDR 32 at %lx, ret %lx\n", mem, ret); break; case 0x1000B400: // dma4 chcr ret = ((DMACh *)&PS2MEM_HW[0xb400])->chcr; SPR_LOG("Hardware read IPU1_CHCR 32 at %lx, ret %x\n", mem, ret); break; case 0x1000e010: // DMAC_STAT HW_LOG("DMAC_STAT Read 32bit %x\n", psHu32(0xe010)); return psHu32(0xe010); case 0x1000f000: // INTC_STAT // HW_LOG("INTC_STAT Read 32bit %x\n", psHu32(0xf000)); return psHu32(0xf000); case 0x1000f010: // INTC_MASK HW_LOG("INTC_MASK Read 32bit %x\n", psHu32(0xf010)); return psHu32(0xf010); #endif case 0x1000f130: case 0x1000f410: case 0x1000f430: ret = 0; break; case 0x1000f440: b440++; switch (b440) { case 3: case 6: case 9: case 10: case 13: case 14: case 17: case 18: case 21: case 22: case 25: case 26: case 29: case 30: ret = 0; break; default: ret = 0x1f; break; } break; case 0x1000f520: // DMAC_ENABLER #ifdef HW_LOG HW_LOG("DMAC_ENABLER Read 32bit %lx\n", psHu32(0xf590)); #endif return psHu32(0xf590); default: if ((mem & 0xffffff0f) == 0x1000f200) { // SIF Control Registers /*1D000020 (word) - EE -> IOP status flag ( set to 0x10000 always ready ) 1D000030 (word) - IOP -> EE status flag 1D000040 (word) - See psxMem.c ( Initially set to 0xF00042 and reset to to this value if 0x20 is written ) 1D000060 (word) - used to detect whether the SIF interface exists read must be 0x1D000060, or the top 20 bits must be zero */ // note, any changes you make in here, also make on recMemRead32 if(mem ==0x1000f260) ret = 0; else if(mem == 0x1000F240) { ret = psHu32(mem) | 0xF0000102; //psHu32(mem) &= ~0x4000; } else ret = psHu32(mem); //#ifdef HW_LOG // SysPrintf("sif %x(%x) Read 32bit %x\n", mem, 0xbd000000 | (mem & 0xf0),ret); //#endif } break; } else if (mem < 0x10010000) { ret = psHu32(mem); } else { SysPrintf("32bit HW read of address 0x%x\n", mem); ret = 0; } #ifdef HW_LOG HW_LOG("Unknown Hardware Read 32 at %lx, ret %lx\n", mem, ret); #endif break; } return ret; } 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((u32)rcntRcount); ADD32ItoR(ESP, 4); return 1; case 0x10000010: _eeReadConstMem32(x86reg, (u32)&counters[0].mode); return 0; case 0x10000020: _eeReadConstMem32(x86reg, (u32)&counters[0].target); return 0; case 0x10000030: _eeReadConstMem32(x86reg, (u32)&counters[0].hold); return 0; case 0x10000800: iFlushCall(0); PUSH32I(1); CALLFunc((u32)rcntRcount); ADD32ItoR(ESP, 4); return 1; case 0x10000810: _eeReadConstMem32(x86reg, (u32)&counters[1].mode); return 0; case 0x10000820: _eeReadConstMem32(x86reg, (u32)&counters[1].target); return 0; case 0x10000830: _eeReadConstMem32(x86reg, (u32)&counters[1].hold); return 0; case 0x10001000: iFlushCall(0); PUSH32I(2); CALLFunc((u32)rcntRcount); ADD32ItoR(ESP, 4); return 1; case 0x10001010: _eeReadConstMem32(x86reg, (u32)&counters[2].mode); return 0; case 0x10001020: _eeReadConstMem32(x86reg, (u32)&counters[2].target); return 0; case 0x10001030: _eeReadConstMem32(x86reg, (u32)&counters[2].hold); return 0; case 0x10001800: iFlushCall(0); PUSH32I(3); CALLFunc((u32)rcntRcount); ADD32ItoR(ESP, 4); return 1; case 0x10001810: _eeReadConstMem32(x86reg, (u32)&counters[3].mode); return 0; case 0x10001820: _eeReadConstMem32(x86reg, (u32)&counters[3].target); return 0; case 0x10001830: _eeReadConstMem32(x86reg, (u32)&counters[3].hold); return 0; case 0x1000f130: case 0x1000f410: case 0x1000f430: if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); else XOR32RtoR(x86reg, x86reg); return 0; case 0x1000f440: //iMemRead32Check(); // increment and test INC32M((int)&b440); MOV32MtoR(EAX, (int)&b440); SUB32ItoR(EAX, 3); MOV32ItoR(EDX, 31); CMP32ItoR(EAX, 27); // look up table j8Ptr[8] = JA8(0); SHL32ItoR(EAX, 2); ADD32ItoR(EAX, (int)b440table); MOV32RmtoR(EDX, EAX); x86SetJ8( j8Ptr[8] ); MOV32RtoM( (int)PS2MEM_HW+0xf440, EDX); if( IS_XMMREG(x86reg) ) SSE2_MOVD_R_to_XMM(x86reg&0xf, EDX); else if( IS_MMXREG(x86reg) ) MOVD32RtoMMX(x86reg&0xf, EDX); else MOV32RtoR(x86reg, EDX); return 0; case 0x1000f520: // DMAC_ENABLER _eeReadConstMem32(x86reg, (u32)&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); 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, (u32)&PS2MEM_HW[(mem) & 0xffff]); SSEX_POR_M128_to_XMM(x86reg&0xf, (u32)&s_regreads[2]); } else if( IS_MMXREG(x86reg) ) { MOVDMtoMMX(x86reg&0xf, (u32)&PS2MEM_HW[(mem) & 0xffff]); PORMtoR(x86reg&0xf, (u32)&s_regreads[2]); } else { MOV32MtoR(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); OR32ItoR(x86reg, 0xF0000102); } return 0; } } if (mem < 0x10010000) { _eeReadConstMem32(x86reg, (u32)&PS2MEM_HW[(mem) & 0xffff]); } else { if( IS_XMMREG(x86reg) ) SSEX_PXOR_XMM_to_XMM(x86reg&0xf, x86reg&0xf); else if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf); else XOR32RtoR(x86reg, x86reg); } return 0; } } u64 hwRead64(u32 mem) { u64 ret; if ((mem>=0x10002000) && (mem<0x10003000)) { return ipuRead64(mem); } switch (mem) { default: if (mem < 0x10010000) { ret = psHu64(mem); } else ret = 0; #ifdef HW_LOG HW_LOG("Unknown Hardware Read 64 at %x\n",mem); #endif break; } return ret; } 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, (u32)PSM(mem)); else { MOVQMtoR(mmreg, (u32)PSM(mem)); SetMMXstate(); } } void hwRead128(u32 mem, u64 *out) { if (mem >= 0x10004000 && mem < 0x10008000) { ReadFIFO(mem, out); return; } if (mem < 0x10010000) { out[0] = psHu64(mem); out[1] = psHu64(mem+8); } #ifdef HW_LOG HW_LOG("Unknown Hardware Read 128 at %x\n",mem); #endif } __declspec(align(16)) u32 s_TempFIFO[4]; void hwConstRead128(u32 mem, int xmmreg) { if (mem >= 0x10004000 && mem < 0x10008000) { iFlushCall(0); PUSH32I((u32)&s_TempFIFO[0]); PUSH32I(mem); CALLFunc((u32)ReadFIFO); ADD32ItoR(ESP, 8); _eeReadConstMem128( xmmreg, (u32)&s_TempFIFO[0]); return; } _eeReadConstMem128( xmmreg, (u32)PSM(mem)); } // dark cloud2 uses it #define DmaExec8(name, num) { \ psHu8(mem) = (u8)value; \ if ((psHu8(mem) & 0x1) && (psHu32(DMAC_CTRL) & 0x1)) { \ /*SysPrintf("Running DMA 8 %x\n", psHu32(mem & ~0x1));*/ \ dma##name(); \ } \ } // when writing imm #define recDmaExecI8(name, num) { \ MOV8ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); \ if( g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 1 ) { \ TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ j8Ptr[6] = JZ8(0); \ CALLFunc((u32)dma##name); \ x86SetJ8( j8Ptr[6] ); \ } \ } \ #define recDmaExec8(name, num) { \ iFlushCall(0); \ if( IS_CONSTREG(mmreg) ) { \ recDmaExecI8(name, num); \ } \ else { \ _eeMoveMMREGtoR(EAX, mmreg); \ _eeWriteConstMem8((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ \ TEST8ItoR(EAX, 1); \ j8Ptr[5] = JZ8(0); \ TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ j8Ptr[6] = JZ8(0); \ \ CALLFunc((u32)dma##name); \ \ x86SetJ8( j8Ptr[5] ); \ x86SetJ8( j8Ptr[6] ); \ } \ } \ char sio_buffer[1024]; static int sio_count; void hwWrite8(u32 mem, u8 value) { #ifdef PCSX2_DEVBUILD if( mem >= 0x10000000 && mem < 0x10008000 ) SysPrintf("hwWrite8 to %x\n", mem); #endif switch (mem) { case 0x10000000: rcntWcount(0, value); break; case 0x10000010: rcntWmode(0, value); break; case 0x10000020: rcntWtarget(0, value); break; case 0x10000030: rcntWhold(0, value); break; case 0x10000800: rcntWcount(1, value); break; case 0x10000810: rcntWmode(1, value); break; case 0x10000820: rcntWtarget(1, value); break; case 0x10000830: rcntWhold(1, value); break; case 0x10001000: rcntWcount(2, value); break; case 0x10001010: rcntWmode(2, value); break; case 0x10001020: rcntWtarget(2, value); break; case 0x10001800: rcntWcount(3, value); break; case 0x10001810: rcntWmode(3, value); break; case 0x10001820: rcntWtarget(3, value); break; case 0x1000f180: 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; } } // SysPrintf("%c", value); break; case 0x10008001: // dma0 - vif0 #ifdef DMA_LOG DMA_LOG("VIF0dma %lx\n", value); #endif DmaExec8(VIF0, 0); break; case 0x10009001: // dma1 - vif1 #ifdef DMA_LOG DMA_LOG("VIF1dma %lx\n", value); #endif DmaExec8(VIF1, 1); break; case 0x1000a001: // dma2 - gif #ifdef DMA_LOG DMA_LOG("0x%8.8x hwWrite8: GSdma %lx 0x%lx\n", cpuRegs.cycle, value); #endif DmaExec8(GIF, 2); break; case 0x1000b001: // dma3 - fromIPU #ifdef DMA_LOG DMA_LOG("IPU0dma %lx\n", value); #endif DmaExec8(IPU0, 3); break; case 0x1000b401: // dma4 - toIPU #ifdef DMA_LOG DMA_LOG("IPU1dma %lx\n", value); #endif DmaExec8(IPU1, 4); break; case 0x1000c001: // dma5 - sif0 #ifdef DMA_LOG DMA_LOG("SIF0dma %lx\n", value); #endif // if (value == 0) psxSu32(0x30) = 0x40000; DmaExec8(SIF0, 5); break; case 0x1000c401: // dma6 - sif1 #ifdef DMA_LOG DMA_LOG("SIF1dma %lx\n", value); #endif DmaExec8(SIF1, 6); break; case 0x1000c801: // dma7 - sif2 #ifdef DMA_LOG DMA_LOG("SIF2dma %lx\n", value); #endif DmaExec8(SIF2, 7); break; case 0x1000d001: // dma8 - fromSPR #ifdef DMA_LOG DMA_LOG("fromSPRdma8 %lx\n", value); #endif DmaExec8(SPR0, 8); break; case 0x1000d401: // dma9 - toSPR #ifdef DMA_LOG DMA_LOG("toSPRdma8 %lx\n", value); #endif DmaExec8(SPR1, 9); break; case 0x1000f592: // DMAC_ENABLEW psHu8(0xf592) = value; psHu8(0xf522) = value; break; default: if ((mem & 0xffffff0f) == 0x1000f200) { u32 at = mem & 0xf0; switch(at) { case 0x00: psHu8(mem) = value; break; case 0x40: if(!(value & 0x100)) psHu32(mem) &= ~0x100; break; } return; } assert( (mem&0xff0f) != 0xf200 ); switch(mem&~3) { case 0x1000f130: case 0x1000f410: case 0x1000f430: break; default: psHu8(mem) = value; } #ifdef HW_LOG HW_LOG("Unknown Hardware write 8 at %x with value %x\n", mem, value); #endif break; } } 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_CONSTREG(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((u32)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((u32)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( (u32)&PS2MEM_HW[0xf522], mmreg ); _eeWriteConstMem8( (u32)&PS2MEM_HW[0xf592], mmreg ); break; default: if ((mem & 0xffffff0f) == 0x1000f200) { u32 at = mem & 0xf0; switch(at) { case 0x00: _eeWriteConstMem8( (u32)&PS2MEM_HW[mem&0xffff], mmreg); break; case 0x40: if( IS_CONSTREG(mmreg) ) { if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { AND32ItoM( (u32)&PS2MEM_HW[mem&0xfffc], ~0x100); } } else { _eeMoveMMREGtoR(EAX, mmreg); TEST16ItoR(EAX, 0x100); j8Ptr[5] = JNZ8(0); AND32ItoM( (u32)&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 WIN32_VIRTUAL_MEM //NOTE: this might cause crashes, but is more correct _eeWriteConstMem8((u32)PS2MEM_BASE + mem, mmreg); #else if (mem < 0x10010000) { _eeWriteConstMem8((u32)&PS2MEM_HW[mem&0xffff], mmreg); } #endif } break; } } #define DmaExec16(name, num) { \ psHu16(mem) = (u16)value; \ if ((psHu16(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1)) { \ SysPrintf("16bit DMA Start\n"); \ dma##name(); \ } \ } #define recDmaExecI16(name, num) { \ MOV16ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); \ if( g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100 ) { \ TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ j8Ptr[6] = JZ8(0); \ CALLFunc((u32)dma##name); \ x86SetJ8( j8Ptr[6] ); \ } \ } \ #define recDmaExec16(name, num) { \ iFlushCall(0); \ if( IS_CONSTREG(mmreg) ) { \ recDmaExecI16(name, num); \ } \ else { \ _eeMoveMMREGtoR(EAX, mmreg); \ _eeWriteConstMem16((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ \ TEST8ItoR(EAX, 0x100); \ j8Ptr[5] = JZ8(0); \ TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ j8Ptr[6] = JZ8(0); \ \ CALLFunc((u32)dma##name); \ \ x86SetJ8( j8Ptr[5] ); \ x86SetJ8( j8Ptr[6] ); \ } \ } \ void hwWrite16(u32 mem, u16 value) { #ifdef PCSX2_DEVBUILD if( mem >= 0x10000000 && mem < 0x10008000 ) SysPrintf("hwWrite16 to %x\n", mem); #endif switch(mem) { case 0x10008000: // dma0 - vif0 #ifdef DMA_LOG DMA_LOG("VIF0dma %lx\n", value); #endif DmaExec16(VIF0, 0); break; // Latest Fix for Florin by asadr (VIF1) case 0x10009000: // dma1 - vif1 - chcr #ifdef DMA_LOG DMA_LOG("VIF1dma CHCR %lx\n", value); #endif DmaExec16(VIF1, 1); break; #ifdef HW_LOG case 0x10009010: // dma1 - vif1 - madr HW_LOG("VIF1dma Madr %lx\n", value); psHu32(mem) = value;//dma1 madr break; case 0x10009020: // dma1 - vif1 - qwc HW_LOG("VIF1dma QWC %lx\n", value); psHu32(mem) = value;//dma1 qwc break; case 0x10009030: // dma1 - vif1 - tadr HW_LOG("VIF1dma TADR %lx\n", value); psHu32(mem) = value;//dma1 tadr break; case 0x10009040: // dma1 - vif1 - asr0 HW_LOG("VIF1dma ASR0 %lx\n", value); psHu32(mem) = value;//dma1 asr0 break; case 0x10009050: // dma1 - vif1 - asr1 HW_LOG("VIF1dma ASR1 %lx\n", value); psHu32(mem) = value;//dma1 asr1 break; case 0x10009080: // dma1 - vif1 - sadr HW_LOG("VIF1dma SADR %lx\n", value); psHu32(mem) = value;//dma1 sadr break; #endif // --------------------------------------------------- case 0x1000a000: // dma2 - gif #ifdef DMA_LOG DMA_LOG("0x%8.8x hwWrite32: GSdma %lx\n", cpuRegs.cycle, value); #endif DmaExec16(GIF, 2); break; #ifdef HW_LOG case 0x1000a010: psHu32(mem) = value;//dma2 madr HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x\n",mem,value); break; case 0x1000a020: psHu32(mem) = value;//dma2 qwc HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x\n",mem,value); break; case 0x1000a030: psHu32(mem) = value;//dma2 taddr HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x\n",mem,value); break; case 0x1000a040: psHu32(mem) = value;//dma2 asr0 HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x\n",mem,value); break; case 0x1000a050: psHu32(mem) = value;//dma2 asr1 HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x\n",mem,value); break; case 0x1000a080: psHu32(mem) = value;//dma2 saddr HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x\n",mem,value); break; #endif case 0x1000b000: // dma3 - fromIPU #ifdef DMA_LOG DMA_LOG("IPU0dma %lx\n", value); #endif DmaExec16(IPU0, 3); break; #ifdef HW_LOG case 0x1000b010: psHu32(mem) = value;//dma2 madr HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x\n",mem,value); break; case 0x1000b020: psHu32(mem) = value;//dma2 madr HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x\n",mem,value); break; case 0x1000b030: psHu32(mem) = value;//dma2 tadr HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x\n",mem,value); break; case 0x1000b080: psHu32(mem) = value;//dma2 saddr HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x\n",mem,value); break; #endif case 0x1000b400: // dma4 - toIPU #ifdef DMA_LOG DMA_LOG("IPU1dma %lx\n", value); #endif DmaExec16(IPU1, 4); break; #ifdef HW_LOG case 0x1000b410: psHu32(mem) = value;//dma2 madr HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x\n",mem,value); break; case 0x1000b420: psHu32(mem) = value;//dma2 madr HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x\n",mem,value); break; case 0x1000b430: psHu32(mem) = value;//dma2 tadr HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x\n",mem,value); break; case 0x1000b480: psHu32(mem) = value;//dma2 saddr HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x\n",mem,value); break; #endif case 0x1000c000: // dma5 - sif0 #ifdef DMA_LOG DMA_LOG("SIF0dma %lx\n", value); #endif // if (value == 0) psxSu32(0x30) = 0x40000; DmaExec16(SIF0, 5); break; case 0x1000c002: //? break; case 0x1000c400: // dma6 - sif1 #ifdef DMA_LOG DMA_LOG("SIF1dma %lx\n", value); #endif DmaExec16(SIF1, 6); break; #ifdef HW_LOG case 0x1000c420: // dma6 - sif1 - qwc HW_LOG("SIF1dma QWC = %lx\n", value); psHu32(mem) = value; break; #endif #ifdef HW_LOG case 0x1000c430: // dma6 - sif1 - tadr HW_LOG("SIF1dma TADR = %lx\n", value); psHu32(mem) = value; break; #endif case 0x1000c800: // dma7 - sif2 #ifdef DMA_LOG DMA_LOG("SIF2dma %lx\n", value); #endif DmaExec16(SIF2, 7); break; case 0x1000c802: //? break; case 0x1000d000: // dma8 - fromSPR #ifdef DMA_LOG DMA_LOG("fromSPRdma %lx\n", value); #endif DmaExec16(SPR0, 8); break; case 0x1000d400: // dma9 - toSPR #ifdef DMA_LOG DMA_LOG("toSPRdma %lx\n", value); #endif DmaExec16(SPR1, 9); break; case 0x1000f592: // DMAC_ENABLEW psHu16(0xf592) = value; psHu16(0xf522) = value; break; case 0x1000f130: case 0x1000f132: case 0x1000f410: case 0x1000f412: case 0x1000f430: case 0x1000f432: break; default: if ((mem & 0xffffff0f) == 0x1000f200) { u32 at = mem & 0xf0; switch(at) { case 0x00: psHu16(mem) = value; break; case 0x20: psHu16(mem) |= value; break; case 0x30: psHu16(mem) &= ~value; break; case 0x40: assert( (mem&2)==0); if(!(value & 0x100)) psHu16(mem) &= ~0x100; else psHu16(mem) |= 0x100; break; case 0x60: psHu16(mem) = 0; break; } return; } assert( (mem&0xff0f) != 0xf200 ); #ifndef WIN32_VIRTUAL_MEM if (mem < 0x10010000) #endif { psHu16(mem) = value; } } #ifdef HW_LOG HW_LOG("Unknown Hardware write 16 at %x with value %x\n",mem,value); #endif } void hwConstWrite16(u32 mem, int mmreg) { switch(mem&~3) { 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((u32)&PS2MEM_HW[0xf522], mmreg); _eeWriteConstMem16((u32)&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((u32)&PS2MEM_HW[mem&0xffff], mmreg); break; case 0x20: _eeWriteConstMem16OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 1); break; case 0x30: if( IS_CONSTREG(mmreg) ) { AND16ItoM((u32)&PS2MEM_HW[mem&0xffff], ~g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]); } else { NOT32R(mmreg&0xf); AND16RtoM((u32)&PS2MEM_HW[mem&0xffff], mmreg&0xf); } break; case 0x40: if( IS_CONSTREG(mmreg) ) { if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { AND16ItoM((u32)&PS2MEM_HW[mem&0xffff], ~0x100); } else { OR16ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); } } else { _eeMoveMMREGtoR(EAX, mmreg); TEST16ItoR(EAX, 0x100); j8Ptr[5] = JZ8(0); OR16ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); j8Ptr[6] = JMP8(0); x86SetJ8( j8Ptr[5] ); AND16ItoM((u32)&PS2MEM_HW[mem&0xffff], ~0x100); x86SetJ8( j8Ptr[6] ); } break; case 0x60: _eeWriteConstMem16((u32)&PS2MEM_HW[mem&0xffff], 0); break; } return; } #ifdef WIN32_VIRTUAL_MEM //NOTE: this might cause crashes, but is more correct _eeWriteConstMem16((u32)PS2MEM_BASE + mem, mmreg); #else if (mem < 0x10010000) { _eeWriteConstMem16((u32)&PS2MEM_HW[mem&0xffff], mmreg); } #endif } } #define DmaExec(name, num) { \ /* why not allowing tags on sif0/sif2? */ \ if(mem!= 0x1000c000/* && mem != 0x1000c400*/ && mem != 0x1000c800) \ psHu32(mem) = (psHu32(mem) & 0xFFFF0000) | (u16)value; \ else \ psHu32(mem) = (u32)value; \ if ((psHu32(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1)) { \ dma##name(); \ } \ } // when writing an Imm #define recDmaExecI(name, num) { \ u32 c = g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0]; \ if(mem!= 0x1000c000 && mem != 0x1000c800) MOV16ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], c); \ else MOV32ItoM((u32)&PS2MEM_HW[(mem) & 0xffff], c); \ if( c & 0x100 ) { \ TEST8ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ j8Ptr[6] = JZ8(0); \ CALLFunc((u32)dma##name); \ x86SetJ8( j8Ptr[6] ); \ } \ } \ #define recDmaExec(name, num) { \ iFlushCall(0); \ if( IS_CONSTREG(mmreg) ) { \ recDmaExecI(name, num); \ } \ else { \ _eeMoveMMREGtoR(EAX, mmreg); \ if(mem!= 0x1000c000 && mem != 0x1000c800) { \ if( IS_XMMREG(mmreg) || IS_MMXREG(mmreg) ) { \ MOV16RtoM((u32)&PS2MEM_HW[(mem) & 0xffff], EAX); \ } \ else { \ _eeWriteConstMem16((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ } \ } \ else _eeWriteConstMem32((u32)&PS2MEM_HW[(mem) & 0xffff], mmreg); \ \ TEST16ItoR(EAX, 0x100); \ j8Ptr[5] = JZ8(0); \ TEST32ItoM((u32)&PS2MEM_HW[DMAC_CTRL&0xffff], 1); \ j8Ptr[6] = JZ8(0); \ \ CALLFunc((u32)dma##name); \ \ x86SetJ8( j8Ptr[5] ); \ x86SetJ8( j8Ptr[6] ); \ } \ } \ void hwWrite32(u32 mem, u32 value) { int i; //IPU regs if ((mem>=0x10002000) && (mem<0x10003000)) { //psHu32(mem) = value; ipuWrite32(mem,value); return; } if ((mem>=0x10003800) && (mem<0x10003c00)) { vif0Write32(mem, value); return; } if ((mem>=0x10003c00) && (mem<0x10004000)) { vif1Write32(mem, value); return; } switch (mem) { case 0x10000000: rcntWcount(0, value); break; case 0x10000010: rcntWmode(0, value); break; case 0x10000020: rcntWtarget(0, value); break; case 0x10000030: rcntWhold(0, value); break; case 0x10000800: rcntWcount(1, value); break; case 0x10000810: rcntWmode(1, value); break; case 0x10000820: rcntWtarget(1, value); break; case 0x10000830: rcntWhold(1, value); break; case 0x10001000: rcntWcount(2, value); break; case 0x10001010: rcntWmode(2, value); break; case 0x10001020: rcntWtarget(2, value); break; case 0x10001800: rcntWcount(3, value); break; case 0x10001810: rcntWmode(3, value); break; case 0x10001820: rcntWtarget(3, value); break; case GIF_CTRL: //SysPrintf("GIF_CTRL write %x\n", value); psHu32(mem) = value & 0x8; if(value & 0x1) { gsGIFReset(); //gsReset(); } else { if( value & 8 ) psHu32(GIF_STAT) |= 8; else psHu32(GIF_STAT) &= ~8; } return; case GIF_MODE: // need to set GIF_MODE (hamster ball) psHu32(GIF_MODE) = value; if (value & 0x1) psHu32(GIF_STAT)|= 0x1; else psHu32(GIF_STAT)&= ~0x1; if (value & 0x4) psHu32(GIF_STAT)|= 0x4; else psHu32(GIF_STAT)&= ~0x4; break; case GIF_STAT: // stat is readonly SysPrintf("Gifstat write value = %x\n", value); return; case 0x10008000: // dma0 - vif0 #ifdef DMA_LOG DMA_LOG("VIF0dma %lx\n", value); #endif DmaExec(VIF0, 0); break; // Latest Fix for Florin by asadr (VIF1) case 0x10009000: // dma1 - vif1 - chcr #ifdef DMA_LOG DMA_LOG("VIF1dma CHCR %lx\n", value); #endif DmaExec(VIF1, 1); break; #ifdef HW_LOG case 0x10009010: // dma1 - vif1 - madr HW_LOG("VIF1dma Madr %lx\n", value); psHu32(mem) = value;//dma1 madr break; case 0x10009020: // dma1 - vif1 - qwc HW_LOG("VIF1dma QWC %lx\n", value); psHu32(mem) = value;//dma1 qwc break; case 0x10009030: // dma1 - vif1 - tadr HW_LOG("VIF1dma TADR %lx\n", value); psHu32(mem) = value;//dma1 tadr break; case 0x10009040: // dma1 - vif1 - asr0 HW_LOG("VIF1dma ASR0 %lx\n", value); psHu32(mem) = value;//dma1 asr0 break; case 0x10009050: // dma1 - vif1 - asr1 HW_LOG("VIF1dma ASR1 %lx\n", value); psHu32(mem) = value;//dma1 asr1 break; case 0x10009080: // dma1 - vif1 - sadr HW_LOG("VIF1dma SADR %lx\n", value); psHu32(mem) = value;//dma1 sadr break; #endif // --------------------------------------------------- case 0x1000a000: // dma2 - gif #ifdef DMA_LOG DMA_LOG("0x%8.8x hwWrite32: GSdma %lx\n", cpuRegs.cycle, value); #endif DmaExec(GIF, 2); break; #ifdef HW_LOG case 0x1000a010: psHu32(mem) = value;//dma2 madr HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x\n",mem,value); break; case 0x1000a020: psHu32(mem) = value;//dma2 qwc HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x\n",mem,value); break; case 0x1000a030: psHu32(mem) = value;//dma2 taddr HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x\n",mem,value); break; case 0x1000a040: psHu32(mem) = value;//dma2 asr0 HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x\n",mem,value); break; case 0x1000a050: psHu32(mem) = value;//dma2 asr1 HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x\n",mem,value); break; case 0x1000a080: psHu32(mem) = value;//dma2 saddr HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x\n",mem,value); break; #endif case 0x1000b000: // dma3 - fromIPU #ifdef DMA_LOG DMA_LOG("IPU0dma %lx\n", value); #endif DmaExec(IPU0, 3); break; #ifdef HW_LOG case 0x1000b010: psHu32(mem) = value;//dma2 madr HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x\n",mem,value); break; case 0x1000b020: psHu32(mem) = value;//dma2 madr HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x\n",mem,value); break; case 0x1000b030: psHu32(mem) = value;//dma2 tadr HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x\n",mem,value); break; case 0x1000b080: psHu32(mem) = value;//dma2 saddr HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x\n",mem,value); break; #endif case 0x1000b400: // dma4 - toIPU #ifdef DMA_LOG DMA_LOG("IPU1dma %lx\n", value); #endif DmaExec(IPU1, 4); break; #ifdef HW_LOG case 0x1000b410: psHu32(mem) = value;//dma2 madr HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x\n",mem,value); break; case 0x1000b420: psHu32(mem) = value;//dma2 madr HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x\n",mem,value); break; case 0x1000b430: psHu32(mem) = value;//dma2 tadr HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x\n",mem,value); break; case 0x1000b480: psHu32(mem) = value;//dma2 saddr HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x\n",mem,value); break; #endif case 0x1000c000: // dma5 - sif0 #ifdef DMA_LOG DMA_LOG("SIF0dma %lx\n", value); #endif // if (value == 0) psxSu32(0x30) = 0x40000; DmaExec(SIF0, 5); break; case 0x1000c400: // dma6 - sif1 #ifdef DMA_LOG DMA_LOG("SIF1dma %lx\n", value); #endif DmaExec(SIF1, 6); break; #ifdef HW_LOG case 0x1000c420: // dma6 - sif1 - qwc HW_LOG("SIF1dma QWC = %lx\n", value); psHu32(mem) = value; break; #endif #ifdef HW_LOG case 0x1000c430: // dma6 - sif1 - tadr HW_LOG("SIF1dma TADR = %lx\n", value); psHu32(mem) = value; break; #endif case 0x1000c800: // dma7 - sif2 #ifdef DMA_LOG DMA_LOG("SIF2dma %lx\n", value); #endif DmaExec(SIF2, 7); break; case 0x1000d000: // dma8 - fromSPR #ifdef DMA_LOG DMA_LOG("fromSPRdma %lx\n", value); #endif DmaExec(SPR0, 8); break; case 0x1000d400: // dma9 - toSPR #ifdef DMA_LOG DMA_LOG("toSPRdma %lx\n", value); #endif DmaExec(SPR1, 9); break; #ifdef HW_LOG case 0x1000e000: // DMAC_CTRL HW_LOG("DMAC_CTRL Write 32bit %x\n", value); psHu32(mem) = value; break; #endif case 0x1000e010: // DMAC_STAT #ifdef HW_LOG HW_LOG("DMAC_STAT Write 32bit %x\n", value); #endif psHu16(0xe010)&= ~(value & 0xffff); // clear on 1 value = value >> 16; for (i=0; i<16; i++) { // reverse on 1 if (value & (1<=0x10002000) && (mem<0x10003000)) { //psHu32(mem) = value; ipuConstWrite32(mem, mmreg); return; } if ((mem>=0x10003800) && (mem<0x10003c00)) { _recPushReg(mmreg); iFlushCall(0); PUSH32I(mem); CALLFunc((u32)vif0Write32); ADD32ItoR(ESP, 8); return; } if ((mem>=0x10003c00) && (mem<0x10004000)) { _recPushReg(mmreg); iFlushCall(0); PUSH32I(mem); CALLFunc((u32)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((u32)gsGIFReset); j8Ptr[6] = JMP8(0); x86SetJ8( j8Ptr[5] ); AND32I8toR(EAX, 8); MOV32RtoM((u32)&PS2MEM_HW[mem&0xffff], EAX); TEST16ItoR(EAX, 8); j8Ptr[5] = JZ8(0); OR8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], 8); j8Ptr[7] = JMP8(0); x86SetJ8( j8Ptr[5] ); AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~8); x86SetJ8( j8Ptr[6] ); x86SetJ8( j8Ptr[7] ); return; case GIF_MODE: _eeMoveMMREGtoR(EAX, mmreg); _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~5); AND8ItoR(EAX, 5); OR8RtoM((u32)&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((u32)&PS2MEM_HW[0xe010], ECX); SHR32ItoR(EAX, 16); XOR16RtoM((u32)&PS2MEM_HW[0xe012], EAX); MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); AND32ItoR(EAX, 0x10007); CMP32ItoR(EAX, 0x10001); j8Ptr[5] = JNE8(0); CALLFunc((u32)cpuTestDMACInts); x86SetJ8( j8Ptr[5] ); break; case 0x1000f000: // INTC_STAT _eeWriteConstMem32OP((u32)&PS2MEM_HW[0xf000], mmreg, 2); break; case 0x1000f010: // INTC_MASK _eeMoveMMREGtoR(EAX, mmreg); iFlushCall(0); XOR16RtoM((u32)&PS2MEM_HW[0xf010], EAX); MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); AND32ItoR(EAX, 0x10007); CMP32ItoR(EAX, 0x10001); j8Ptr[5] = JNE8(0); CALLFunc((u32)cpuTestDMACInts); x86SetJ8( j8Ptr[5] ); break; case 0x1000f590: // DMAC_ENABLEW _eeWriteConstMem32((u32)&PS2MEM_HW[0xf520], mmreg); _eeWriteConstMem32((u32)&PS2MEM_HW[0xf590], mmreg); return; case 0x1000f130: case 0x1000f410: case 0x1000f430: break; default: if ((mem & 0xffffff0f) == 0x1000f200) { u32 at = mem & 0xf0; switch(at) { case 0x00: _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); break; case 0x20: _eeWriteConstMem32OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 1); break; case 0x30: _eeWriteConstMem32OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 2); break; case 0x40: if( IS_CONSTREG(mmreg) ) { if( !(g_cpuConstRegs[(mmreg>>16)&0x1f].UL[0] & 0x100) ) { AND32ItoM( (u32)&PS2MEM_HW[mem&0xfffc], ~0x100); } else { OR32ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); } } else { _eeMoveMMREGtoR(EAX, mmreg); TEST32ItoR(EAX, 0x100); j8Ptr[5] = JZ8(0); OR32ItoM((u32)&PS2MEM_HW[mem&0xffff], 0x100); j8Ptr[6] = JMP8(0); x86SetJ8( j8Ptr[5] ); AND32ItoM((u32)&PS2MEM_HW[mem&0xffff], ~0x100); x86SetJ8( j8Ptr[6] ); } break; case 0x60: MOV32ItoM((u32)&PS2MEM_HW[mem&0xffff], 0); break; } return; } #ifdef WIN32_VIRTUAL_MEM //NOTE: this might cause crashes, but is more correct _eeWriteConstMem32((u32)PS2MEM_BASE + mem, mmreg); #else if (mem < 0x10010000) { _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); } #endif break; } } void hwWrite64(u32 mem, u64 value) { u32 val32; int i; if ((mem>=0x10002000) && (mem<=0x10002030)) { ipuWrite64(mem, value); return; } if ((mem>=0x10003800) && (mem<0x10003c00)) { vif0Write32(mem, value); return; } if ((mem>=0x10003c00) && (mem<0x10004000)) { vif1Write32(mem, value); return; } switch (mem) { case GIF_CTRL: #ifdef PCSX2_DEVBUILD SysPrintf("GIF_CTRL write 64\n", value); #endif psHu32(mem) = value & 0x8; if(value & 0x1) { gsGIFReset(); //gsReset(); } else { if( value & 8 ) psHu32(GIF_STAT) |= 8; else psHu32(GIF_STAT) &= ~8; } return; case GIF_MODE: psHu64(GIF_MODE) = value; if (value & 0x1) psHu32(GIF_STAT)|= 0x1; else psHu32(GIF_STAT)&= ~0x1; if (value & 0x4) psHu32(GIF_STAT)|= 0x4; else psHu32(GIF_STAT)&= ~0x4; break; case GIF_STAT: // stat is readonly return; case 0x1000a000: // dma2 - gif #ifdef DMA_LOG DMA_LOG("0x%8.8x hwWrite64: GSdma %lx\n", cpuRegs.cycle, value); #endif DmaExec(GIF, 2); break; #ifdef HW_LOG case 0x1000e000: // DMAC_CTRL HW_LOG("DMAC_CTRL Write 64bit %x\n", value); psHu64(mem) = value; break; #endif case 0x1000e010: // DMAC_STAT #ifdef HW_LOG HW_LOG("DMAC_STAT Write 64bit %x\n", value); #endif val32 = (u32)value; psHu16(0xe010)&= ~(val32 & 0xffff); // clear on 1 val32 = val32 >> 16; for (i=0; i<16; i++) { // reverse on 1 if (val32 & (1<=0x10002000) && (mem<=0x10002030)) { ipuConstWrite64(mem, mmreg); return; } if ((mem>=0x10003800) && (mem<0x10003c00)) { _recPushReg(mmreg); iFlushCall(0); PUSH32I(mem); CALLFunc((u32)vif0Write32); ADD32ItoR(ESP, 8); return; } if ((mem>=0x10003c00) && (mem<0x10004000)) { _recPushReg(mmreg); iFlushCall(0); PUSH32I(mem); CALLFunc((u32)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((u32)gsGIFReset); j8Ptr[6] = JMP8(0); x86SetJ8( j8Ptr[5] ); AND32I8toR(EAX, 8); MOV32RtoM((u32)&PS2MEM_HW[mem&0xffff], EAX); TEST16ItoR(EAX, 8); j8Ptr[5] = JZ8(0); OR8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], 8); j8Ptr[7] = JMP8(0); x86SetJ8( j8Ptr[5] ); AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~8); x86SetJ8( j8Ptr[6] ); x86SetJ8( j8Ptr[7] ); return; case GIF_MODE: _eeMoveMMREGtoR(EAX, mmreg); _eeWriteConstMem32((u32)&PS2MEM_HW[mem&0xffff], mmreg); AND8ItoM((u32)&PS2MEM_HW[GIF_STAT&0xffff], ~5); AND8ItoR(EAX, 5); OR8RtoM((u32)&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((u32)&PS2MEM_HW[0xe010], ECX); SHR32ItoR(EAX, 16); XOR16RtoM((u32)&PS2MEM_HW[0xe012], EAX); MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); AND32ItoR(EAX, 0x10007); CMP32ItoR(EAX, 0x10001); j8Ptr[5] = JNE8(0); CALLFunc((u32)cpuTestDMACInts); x86SetJ8( j8Ptr[5] ); break; case 0x1000f590: // DMAC_ENABLEW _eeWriteConstMem32((u32)&PS2MEM_HW[0xf520], mmreg); _eeWriteConstMem32((u32)&PS2MEM_HW[0xf590], mmreg); break; case 0x1000f000: // INTC_STAT _eeWriteConstMem32OP((u32)&PS2MEM_HW[mem&0xffff], mmreg, 2); break; case 0x1000f010: // INTC_MASK _eeMoveMMREGtoR(EAX, mmreg); iFlushCall(0); XOR16RtoM((u32)&PS2MEM_HW[0xf010], EAX); MOV32MtoR(EAX, (u32)&cpuRegs.CP0.n.Status.val); AND32ItoR(EAX, 0x10007); CMP32ItoR(EAX, 0x10001); j8Ptr[5] = JNE8(0); CALLFunc((u32)cpuTestDMACInts); x86SetJ8( j8Ptr[5] ); break; case 0x1000f130: case 0x1000f410: case 0x1000f430: break; default: _eeWriteConstMem64((u32)PSM(mem), mmreg); break; } } void hwWrite128(u32 mem, u64 *value) { if (mem >= 0x10004000 && mem < 0x10008000) { WriteFIFO(mem, value); return; } switch (mem) { case 0x1000f590: // DMAC_ENABLEW psHu32(0xf590) = *(u32*)value; psHu32(0xf520) = *(u32*)value; break; case 0x1000f130: case 0x1000f410: case 0x1000f430: break; default: psHu64(mem ) = value[0]; psHu64(mem+8) = value[1]; #ifdef PCSX2_DEVBUILD HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)\n", mem, value[1], value[0], cpuRegs.CP0.n.Status); #endif break; } } void hwConstWrite128(u32 mem, int mmreg) { if (mem >= 0x10004000 && mem < 0x10008000) { _eeWriteConstMem128((u32)&s_TempFIFO[0], mmreg); iFlushCall(0); PUSH32I((u32)&s_TempFIFO[0]); PUSH32I(mem); CALLFunc((u32)WriteFIFO); ADD32ItoR(ESP, 8); return; } switch (mem) { case 0x1000f590: // DMAC_ENABLEW _eeWriteConstMem32((u32)&PS2MEM_HW[0xf520], mmreg); _eeWriteConstMem32((u32)&PS2MEM_HW[0xf590], mmreg); break; case 0x1000f130: case 0x1000f410: case 0x1000f430: break; default: #ifdef WIN32_VIRTUAL_MEM _eeWriteConstMem128( PS2MEM_BASE_+mem, mmreg); #else if (mem < 0x10010000) _eeWriteConstMem128((u32)&PS2MEM_HW[mem&0xffff], mmreg); #endif break; } } int intcInterrupt() { if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; if ((psHu32(INTC_STAT)) == 0) { SysPrintf("*PCSX2*: intcInterrupt already cleared\n"); return 1; } if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0) return 0; #ifdef HW_LOG HW_LOG("intcInterrupt %x\n", psHu32(INTC_STAT) & psHu32(INTC_MASK)); #endif if(psHu32(INTC_STAT) & 0x2){ counters[0].hold = rcntRcount(0); counters[1].hold = rcntRcount(1); } cpuException(0x400, cpuRegs.branch); return 1; } int dmacTestInterrupt() { if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; if ((psHu16(0xe012) & psHu16(0xe010) || psHu16(0xe010) & 0x8000) == 0) return 0; if((psHu32(DMAC_CTRL) & 0x1) == 0) return 0; return 1; } int dmacInterrupt() { if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return 0; if ((psHu16(0xe012) & psHu16(0xe010) || psHu16(0xe010) & 0x8000) == 0) return 0; if((psHu32(DMAC_CTRL) & 0x1) == 0) return 0; #ifdef HW_LOG HW_LOG("dmacInterrupt %x\n", (psHu16(0xe012) & psHu16(0xe010) || psHu16(0xe010) & 0x8000)); #endif cpuException(0x800, cpuRegs.branch); return 1; } void hwIntcIrq(int n) { //if( psHu32(INTC_MASK) & (1< (maddr+msize)) { // int s1 = (maddr+msize) - addr; // int s2 = size - s1; // // /* it does, so first copy 's1' bytes from 'addr' to 'data' */ // src = PSM(addr); // if (src == NULL) return -1; // memcpy_amd(data, src, s1); // // /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ // src = PSM(maddr); // if (src == NULL) return -1; // memcpy(&data[s1], src, s2); // } else { // //u32 * tempptr, * tempptr2; // /* it doesn't, so just copy 'size' bytes from 'addr' to 'data' */ // src = PSM(addr); // if (src == NULL) return -1; // //tempptr = (u32*)src; // //tempptr2 = (u32*)data; // // memcpy(data, src, size); // } // // return 0; //} /* Write 'size' bytes to memory address 'addr' from 'data'. */ int hwMFIFOWrite(u32 addr, u8 *data, int size) { u32 maddr = psHu32(DMAC_RBOR); int msize = psHu32(DMAC_RBSR)+16; u8 *dst; addr = psHu32(DMAC_RBOR) + (addr & psHu32(DMAC_RBSR)); /* Check if the transfer should wrap around the ring buffer */ if ((addr+size) > (maddr+msize)) { int s1 = (maddr+msize) - addr; int s2 = size - s1; /* it does, so first copy 's1' bytes from 'data' to 'addr' */ dst = PSM(addr); if (dst == NULL) return -1; Cpu->Clear(addr, s1/4); memcpy(dst, data, s1); /* and second copy 's2' bytes from '&data[s1]' to 'maddr' */ dst = PSM(maddr); if (dst == NULL) return -1; Cpu->Clear(maddr, s2/4); memcpy(dst, &data[s1], s2); } else { //u32 * tempptr, * tempptr2; /* it doesn't, so just copy 'size' bytes from 'data' to 'addr' */ dst = PSM(addr); if (dst == NULL) return -1; Cpu->Clear(addr, size/4); memcpy_amd(dst, data, size); } return 0; } int hwDmacSrcChainWithStack(DMACh *dma, int id) { u32 temp,finalAddress; switch (id) { case 0: // Refe - Transfer Packet According to ADDR field //dma->tadr += 16; return 1; //End Transfer case 1: // CNT - Transfer QWC following the tag. dma->madr = dma->tadr + 16; //Set MADR to QW after Tag dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data return 0; case 2: // Next - Transfer QWC following tag. TADR = ADDR temp = dma->madr; //Temporarily Store ADDR dma->madr = dma->tadr + 16; //Set MADR to QW following the tag dma->tadr = temp; //Copy temporarily stored ADDR to Tag return 0; case 3: // Ref - Transfer QWC from ADDR field case 4: // Refs - Transfer QWC from ADDR field (Stall Control) dma->tadr += 16; //Set TADR to next tag return 0; case 5: // Call - Transfer QWC following the tag, save succeeding tag temp = dma->madr; //Temporarily Store ADDR finalAddress = dma->tadr + 16 + (dma->qwc << 4); //Store Address of Succeeding tag if (dma->asr0 == 0) //Check if ASR0 is empty dma->asr0 = finalAddress; //If yes store Succeeding tag else dma->asr1 = finalAddress; //If no store Succeeding tag in ASR1 dma->madr = dma->tadr + 16; //Set MADR to data following the tag dma->tadr = temp; //Set TADR to temporarily stored ADDR return 0; case 6: // Ret - Transfer QWC following the tag, load next tag dma->madr = dma->tadr + 16; //Set MADR to data following the tag if (dma->asr1 != 0) { //If ASR1 is NOT equal to 0 (Contains address) dma->tadr = dma->asr1; //Read ASR1 as next tag dma->asr1 = 0; //Clear ASR1 } else { //If ASR1 is empty (No address held) if(dma->asr0 != 0) { //Check if ASR0 is NOT equal to 0 (Contains address) dma->tadr = dma->asr0; //Read ASR0 as next tag dma->asr0 = 0; //Clear ASR0 } else { //Else if ASR1 and ASR0 are empty dma->tadr = 0; //Clear tag address return 1; //End Transfer } } return 0; case 7: // End - Transfer QWC following the tag dma->madr = dma->tadr + 16; //Set MADR to data following the tag //comment out tadr fixes lemans //dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data return 1; //End Transfer } return -1; } int hwDmacSrcChain(DMACh *dma, int id) { u32 temp; switch (id) { case 0: // Refe - Transfer Packet According to ADDR field //dma->tadr += 16; return 1; //End Transfer case 1: // CNT - Transfer QWC following the tag. dma->madr = dma->tadr + 16; //Set MADR to QW after Tag dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data return 0; case 2: // Next - Transfer QWC following tag. TADR = ADDR temp = dma->madr; //Temporarily Store ADDR dma->madr = dma->tadr + 16; //Set MADR to QW following the tag dma->tadr = temp; //Copy temporarily stored ADDR to Tag return 0; case 3: // Ref - Transfer QWC from ADDR field case 4: // Refs - Transfer QWC from ADDR field (Stall Control) dma->tadr += 16; //Set TADR to next tag return 0; case 7: // End - Transfer QWC following the tag dma->madr = dma->tadr + 16; //Set MADR to data following the tag //dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data return 1; //End Transfer } return -1; }