/[pcsx2_0.9.7]/trunk/pcsx2/HwWrite.cpp
ViewVC logotype

Diff of /trunk/pcsx2/HwWrite.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

--- trunk/pcsx2/HwWrite.cpp	2010/09/07 03:24:11	31
+++ trunk/pcsx2/HwWrite.cpp	2010/09/07 11:08:22	62
@@ -16,1224 +16,377 @@
 
 #include "PrecompiledHeader.h"
 #include "Common.h"
-
 #include "Hardware.h"
 
-using namespace R5900;
-
-/////////////////////////////////////////////////////////////////////////
-// DMA Execution Interfaces
-
-static bool QuickDmaExec( void (*func)(), u32 mem)
-{
-	bool ret = false;
-    DMACh *reg = &psH_DMACh(mem);
-
-	if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
-	{
-		Registers::Freeze();
-		func();
-		Registers::Thaw();
-		ret = true;
-	}
+#include "ps2/HwInternal.h"
+#include "ps2/eeHwTraceLog.inl"
 
+using namespace R5900;
 
-	return ret;
-}
+// Shift the middle 8 bits (bits 4-12) into the lower 8 bits.
+// This helps the compiler optimize the switch statement into a lookup table. :)
 
+#define HELPSWITCH(m) (((m)>>4) & 0xff)
+#define mcase(src) case HELPSWITCH(src)
 
-tDMAC_QUEUE QueuedDMA(0);
-u32 oldvalue = 0;
+template< uint page > void __fastcall _hwWrite8(u32 mem, u8 value);
+template< uint page > void __fastcall _hwWrite16(u32 mem, u8 value);
+template< uint page > void __fastcall _hwWrite128(u32 mem, u8 value);
 
-void __fastcall StartQueuedDMA()
-{
-	if (QueuedDMA.VIF0) { DMA_LOG("Resuming DMA for VIF0"); if(QuickDmaExec(dmaVIF0, D0_CHCR) == true) QueuedDMA.VIF0 = false; }
-	if (QueuedDMA.VIF1) { DMA_LOG("Resuming DMA for VIF1"); if(QuickDmaExec(dmaVIF1, D1_CHCR) == true) QueuedDMA.VIF1 = false; }
-	if (QueuedDMA.GIF ) { DMA_LOG("Resuming DMA for GIF" ); if(QuickDmaExec(dmaGIF , D2_CHCR) == true) QueuedDMA.GIF = false; }
-	if (QueuedDMA.IPU0) { DMA_LOG("Resuming DMA for IPU0"); if(QuickDmaExec(dmaIPU0, D3_CHCR) == true) QueuedDMA.IPU0 = false; }
-	if (QueuedDMA.IPU1) { DMA_LOG("Resuming DMA for IPU1"); if(QuickDmaExec(dmaIPU1, D4_CHCR) == true) QueuedDMA.IPU1 = false; }
-	if (QueuedDMA.SIF0) { DMA_LOG("Resuming DMA for SIF0"); if(QuickDmaExec(dmaSIF0, D5_CHCR) == true) QueuedDMA.SIF0 = false; }
-	if (QueuedDMA.SIF1) { DMA_LOG("Resuming DMA for SIF1"); if(QuickDmaExec(dmaSIF1, D6_CHCR) == true) QueuedDMA.SIF1 = false; }
-	if (QueuedDMA.SIF2) { DMA_LOG("Resuming DMA for SIF2"); if(QuickDmaExec(dmaSIF2, D7_CHCR) == true) QueuedDMA.SIF2 = false; }
-	if (QueuedDMA.SPR0) { DMA_LOG("Resuming DMA for SPR0"); if(QuickDmaExec(dmaSPR0, D8_CHCR) == true) QueuedDMA.SPR0 = false; }
-	if (QueuedDMA.SPR1) { DMA_LOG("Resuming DMA for SPR1"); if(QuickDmaExec(dmaSPR1, D9_CHCR) == true) QueuedDMA.SPR1 = false; }
-}
 
-// dark cloud2 uses 8 bit DMAs register writes
-static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value )
+template<uint page>
+void __fastcall _hwWrite32( u32 mem, u32 value )
 {
-	DMACh *reg = &psH_DMACh(mem & ~0xf);
+	pxAssume( (mem & 0x03) == 0 );
 
-	//The only thing we can do in an 8bit write is set the CHCR, so lets just do checks for that
+	// Notes:
+	// All unknown registers on the EE are "reserved" as discarded writes and indeterminate
+	// reads.  Bus error is only generated for registers outside the first 16k of mapped
+	// register space (which is handled by the VTLB mapping, so no need for checks here).
 
-	//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
-	if (reg->chcr.STR)
+	switch (page)
 	{
-		if(psHu8(DMAC_ENABLER+2) == 1) //DMA is suspended so we can allow writes to anything
-		{
-			//If it stops the DMA, we need to clear any pending interrupts so the DMA doesnt continue.
-			if(value == 0)
-			{
-				//DevCon.Warning(L"8bit %s DMA Stopped on Suspend", ChcrName(mem & ~0xf));
-				cpuClearInt( ChannelNumber(mem & ~0xf) );
-				QueuedDMA._u16 &= ~(1 << ChannelNumber(mem & ~0xf));
-			}
-			//Here we update the CHCR STR (Busy) bit, we don't touch anything else.
-			reg->chcr.STR = value;
-			return;
-		}
-		else //Else the DMA is running (Not Suspended), so we cant touch it!
-		{
-			//As the manual states "Fields other than STR can only be written to when the DMA is stopped"
-			//Also "The DMA may not stop properly just by writing 0 to STR"
-			//So the presumption is that STR can be written to (ala force stop the DMA) but nothing else
+		case 0x00:	if (!rcntWrite32<0x00>(mem, value)) return;	break;
+		case 0x01:	if (!rcntWrite32<0x01>(mem, value)) return;	break;
 
-			if(value == 0)
-			{
-				//DevCon.Warning(L"8bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem & ~0xf), reg->chcr._u32, value);
-				reg->chcr.STR = value;
-				//We need to clear any existing DMA loops that are in progress else they will continue!
-				cpuClearInt( ChannelNumber(mem&~0xf) );
-				QueuedDMA._u16 &= ~(1 << ChannelNumber(mem&~0xf)); //Clear any queued DMA requests for this channel
-			}
-			//else DevCon.Warning(L"8bit Attempted to stop %s DMA without suspend, ignoring", ChcrName(mem & ~0xf));
-			return;
-		}
+		case 0x02:
+			if (!ipuWrite32(mem, value)) return;
+		break;
 
-	}
+		case 0x04:
+		case 0x05:
+		case 0x06:
+		case 0x07:
+		{
+			// [Ps2Confirm] Direct FIFO read/write behavior.  We need to create a test that writes
+			// data to one of the FIFOs and determine the result.  I'm not quite sure offhand a good
+			// way to do that --air
+			// Current assumption is that 32-bit and 64-bit writes likely do 128-bit zero-filled
+			// writes (upper 96 bits are 0, lower 32 bits are effective).
 
-	reg->chcr.STR = value;
+			u128 zerofill = u128::From32(0);
+			zerofill._u32[(mem >> 2) & 0x03] = value;
 
-	if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
-	{
-		Registers::Freeze();
-		func();
-		Registers::Thaw();
-	}
-	else if(reg->chcr.STR)
-	{
-		//DevCon.Warning(L"8bit %s DMA Start while DMAC Disabled\n",ChcrName(mem));
-		QueuedDMA._u16 |= (1 << ChannelNumber(mem & ~0xf)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted
-	}
-}
+			DevCon.WriteLn( Color_Cyan, "Writing 32-bit FIFO data (zero-extended to 128 bits)" );
+			_hwWrite128<page>(mem & ~0x0f, &zerofill);
+		}
+		return;
 
-static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value )
-{
+		case 0x03:
+			if (mem >= EEMemoryMap::VIF0_Start)
+			{
+				if(mem >= EEMemoryMap::VIF1_Start)
+				{
+					if (!vifWrite32<1>(mem, value)) return;
+				}
+				else
+				{
+					if (!vifWrite32<0>(mem, value)) return;
+				}
+			}
+			else iswitch(mem)
+			{
+				icase(GIF_CTRL)
+				{
+					psHu32(mem) = value & 0x8;
+
+					if (value & 0x1)
+						gsGIFReset();
+
+					if (value & 8)
+						gifRegs.stat.PSE = true;
+					else
+						gifRegs.stat.PSE = false;
+
+					return;
+				}
+
+				icase(GIF_MODE)
+				{
+					// need to set GIF_MODE (hamster ball)
+					gifRegs.mode.write(value);
+
+					// set/clear bits 0 and 2 as per the GIF_MODE value.
+					const u32 bitmask = GIF_MODE_M3R | GIF_MODE_IMT;
+					psHu32(GIF_STAT) &= ~bitmask;
+					psHu32(GIF_STAT) |= (u32)value & bitmask;
 
-    DMACh *reg = &psH_DMACh(mem);
-    tDMA_CHCR chcr(value);
+					return;
+				}
+			}
+		break;
 
-	//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
-	if (reg->chcr.STR)
-	{
-		if(psHu8(DMAC_ENABLER+2) == 1) //DMA is suspended so we can allow writes to anything
+		case 0x08:
+		case 0x09:
+		case 0x0a:
+		case 0x0b:
+		case 0x0c:
+		case 0x0d:
+		case 0x0e:
+			if (!dmacWrite32<page>(mem, value)) return;
+		break;
+		
+		case 0x0f:
 		{
-			//If it stops the DMA, we need to clear any pending interrupts so the DMA doesnt continue.
-			if(chcr.STR == 0)
+			switch( HELPSWITCH(mem) )
 			{
-				//DevCon.Warning(L"16bit %s DMA Stopped on Suspend", ChcrName(mem));
-				cpuClearInt( ChannelNumber(mem) );
-				QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel
-			}
-			//Here we update the lower part of the CHCR, we dont touch the tag as it is only a 16bit value
-			reg->chcr.set((reg->chcr.TAG << 16) | chcr.lower());
-			return;
-		}
-		else //Else the DMA is running (Not Suspended), so we cant touch it!
-		{
-			//As the manual states "Fields other than STR can only be written to when the DMA is stopped"
-			//Also "The DMA may not stop properly just by writing 0 to STR"
-			//So the presumption is that STR can be written to (ala force stop the DMA) but nothing else
+				mcase(INTC_STAT):
+					psHu32(INTC_STAT) &= ~value;
+					//cpuTestINTCInts();
+				return;
+
+				mcase(INTC_MASK):
+					psHu32(INTC_MASK) ^= (u16)value;
+					cpuTestINTCInts();
+				return;
+
+				mcase(SIO_TXFIFO):
+				{
+					u8* woot = (u8*)&value;
+					// [Ps2Confirm] What happens when we write 32 bit values to SIO_TXFIFO?
+					// If it works like the IOP, then all 32 bits are written to the FIFO in
+					// order.  PCSX2 up to this point simply ignored non-8bit writes to this port.
+					_hwWrite8<0x0f>(SIO_TXFIFO, woot[0]);
+					_hwWrite8<0x0f>(SIO_TXFIFO, woot[1]);
+					_hwWrite8<0x0f>(SIO_TXFIFO, woot[2]);
+					_hwWrite8<0x0f>(SIO_TXFIFO, woot[3]);
+				}
+				return;
+
+				mcase(SBUS_F200):
+					// Performs a standard psHu32 assignment (which is the default action anyway).
+					//psHu32(mem) = value;
+				break;
+
+				mcase(SBUS_F220):
+					psHu32(mem) |= value;
+				return;
+
+				mcase(SBUS_F230):
+					psHu32(mem) &= ~value;
+				return;
+
+				mcase(SBUS_F240):
+					if(!(value & 0x100))
+						psHu32(mem) &= ~0x100;
+					else
+						psHu32(mem) |= 0x100;
+				return;
+
+				mcase(SBUS_F260):
+					psHu32(mem) = 0;
+				return;
+
+				mcase(MCH_RICM)://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;	// if SIO repeater is cleared, reset sdevid
+					psHu32(mem) = value & ~0x80000000;	//kill the busy bit
+				return;
+
+				mcase(MCH_DRD):
+					// Performs a standard psHu32 assignment (which is the default action anyway).
+					//psHu32(mem) = value;
+				break;
+
+				mcase(DMAC_ENABLEW):
+					if (!dmacWrite32<0x0f>(DMAC_ENABLEW, value)) return;
+
+				//mcase(SIO_ISR):
+				//mcase(0x1000f410):
+				// Mystery Regs!  No one knows!?
+				// (unhandled so fall through to default)
 
-			if(chcr.STR == 0)
-			{
-				//DevCon.Warning(L"16bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg->chcr._u32, chcr._u32);
-				reg->chcr.STR = 0;
-				//We need to clear any existing DMA loops that are in progress else they will continue!
-				cpuClearInt( ChannelNumber(mem) );
-				QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel
 			}
-			//else DevCon.Warning(L"16bit Attempted to change %s modes while DMA active, ignoring", ChcrName(mem));
-			return;
-		}
-
-	}
-
-	reg->chcr.set((reg->chcr.TAG << 16) | chcr.lower());
-
-	if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
-	{
-		Registers::Freeze();
-		func();
-		Registers::Thaw();
-	}
-	else if(reg->chcr.STR)
-	{
-		//DevCon.Warning(L"16bit %s DMA Start while DMAC Disabled\n",ChcrName(mem));
-		QueuedDMA._u16 |= (1 << ChannelNumber(mem)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted
+		}	
+		break;
 	}
+	
+	psHu32(mem) = value;
 }
 
-static void DmaExec( void (*func)(), u32 mem, u32 value )
+template<uint page>
+void __fastcall hwWrite32( u32 mem, u32 value )
 {
+	eeHwTraceLog( mem, value, false );
+	_hwWrite32<page>( mem, value );
+}
 
-	DMACh *reg = &psH_DMACh(mem);
-    tDMA_CHCR chcr(value);
+// --------------------------------------------------------------------------------------
+//  hwWrite8 / hwWrite16 / hwWrite64 / hwWrite128
+// --------------------------------------------------------------------------------------
 
-	//It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC
-	if (reg->chcr.STR)
+template< uint page >
+void __fastcall _hwWrite8(u32 mem, u8 value)
+{
+	iswitch (mem)
+	icase(SIO_TXFIFO)
 	{
-		if(psHu8(DMAC_ENABLER+2) == 1) //DMA is suspended so we can allow writes to anything
+		static bool iggy_newline = false;
+		static char sio_buffer[1024];
+		static int sio_count;
+
+		if (value == '\r')
 		{
-			//If it stops the DMA, we need to clear any pending interrupts so the DMA doesnt continue.
-			if(chcr.STR == 0)
-			{
-				//DevCon.Warning(L"32bit %s DMA Stopped on Suspend", ChcrName(mem));
-				QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel
-				cpuClearInt( ChannelNumber(mem) );
-			}
-			//Sanity Check for possible future bug fix0rs ;p
-			//Spams on Persona 4 opening.
-			//if(reg->chcr.TAG != chcr.TAG) DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Active", ChcrName(mem), chcr.TAG, reg->chcr.TAG, reg->qwc);
-			//Here we update the LOWER CHCR, if a chain is stopped half way through, it can be manipulated in to a different mode
-			//But we need to preserve the existing tag for now
-			reg->chcr.set((reg->chcr.TAG << 16) | chcr.lower());
-			return;
+			iggy_newline = true;
+			sio_buffer[sio_count++] = '\n';
 		}
-		else //Else the DMA is running (Not Suspended), so we cant touch it!
+		else if (!iggy_newline || (value != '\n'))
 		{
-			//As the manual states "Fields other than STR can only be written to when the DMA is stopped"
-			//Also "The DMA may not stop properly just by writing 0 to STR"
-			//So the presumption is that STR can be written to (ala force stop the DMA) but nothing else
-
-			if(chcr.STR == 0)
-			{
-				//DevCon.Warning(L"32bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg->chcr._u32, chcr._u32);
-				reg->chcr.STR = 0;
-				//We need to clear any existing DMA loops that are in progress else they will continue!
-				cpuClearInt( ChannelNumber(mem) );
-				QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel
-			}
-			//else DevCon.Warning(L"32bit Attempted to change %s CHCR (Currently %x) with %x while DMA active, ignoring QWC = %x", ChcrName(mem), reg->chcr._u32, chcr._u32, reg->qwc);
-			return;
+			iggy_newline = false;
+			sio_buffer[sio_count++] = value;
 		}
 
-	}
-
-	//if(reg->chcr.TAG != chcr.TAG && chcr.MOD == CHAIN_MODE) DevCon.Warning(L"32bit CHCR Tag on %s changed to %x from %x QWC = %x Channel Not Active", ChcrName(mem), chcr.TAG, reg->chcr.TAG, reg->qwc);
-
-	reg->chcr.set(value);
-
-	if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2))
-	{
-		Registers::Freeze();
-		func();
-		Registers::Thaw();
-	}
-	else if(reg->chcr.STR)
-	{
-		//DevCon.Warning(L"32bit %s DMA Start while DMAC Disabled\n", ChcrName(mem));
-		QueuedDMA._u16 |= (1 << ChannelNumber(mem)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted
-	} //else QueuedDMA._u16 &~= (1 << ChannelNumber(mem)); //
-}
-
-/////////////////////////////////////////////////////////////////////////
-// Hardware WRITE 8 bit
-
-char sio_buffer[1024];
-int sio_count;
-
-
-void hwWrite8(u32 mem, u8 value)
-{
-	if ((mem >= VIF0_STAT) && (mem < VIF0_FIFO)) {
-		u32 bytemod = mem & 0x3;
-		u32 bitpos  = 8 * bytemod;
-		u32 oldval  = ~(0xff  << bitpos) & psHu32(mem);
-		u32 newval	=  (value << bitpos) | oldval;
-		if (mem < VIF1_STAT) vif0Write32(mem & ~0x3, newval);
-		else				 vif1Write32(mem & ~0x3, newval);
-		return;
-	}
-
-	if( mem >= IPU_CMD && mem < D0_CHCR )
-		DevCon.Warning( "hwWrite8 to 0x%x = 0x%x", mem, value );
-
-	switch (mem) {
-		case RCNT0_COUNT: rcntWcount(0, value); break;
-		case RCNT0_MODE: rcntWmode(0, (counters[0].modeval & 0xff00) | value); break;
-		case RCNT0_MODE + 1: rcntWmode(0, (counters[0].modeval & 0xff) | value << 8); break;
-		case RCNT0_TARGET: rcntWtarget(0, value); break;
-		case RCNT0_HOLD: rcntWhold(0, value); break;
-
-		case RCNT1_COUNT: rcntWcount(1, value); break;
-		case RCNT1_MODE: rcntWmode(1, (counters[1].modeval & 0xff00) | value); break;
-		case RCNT1_MODE + 1: rcntWmode(1, (counters[1].modeval & 0xff) | value << 8); break;
-		case RCNT1_TARGET: rcntWtarget(1, value); break;
-		case RCNT1_HOLD: rcntWhold(1, value); break;
-
-		case RCNT2_COUNT: rcntWcount(2, value); break;
-		case RCNT2_MODE: rcntWmode(2, (counters[2].modeval & 0xff00) | value); break;
-		case RCNT2_MODE + 1: rcntWmode(2, (counters[2].modeval & 0xff) | value << 8); break;
-		case RCNT2_TARGET: rcntWtarget(2, value); break;
-
-		case RCNT3_COUNT: rcntWcount(3, value); break;
-		case RCNT3_MODE: rcntWmode(3, (counters[3].modeval & 0xff00) | value); break;
-		case RCNT3_MODE + 1: rcntWmode(3, (counters[3].modeval & 0xff) | value << 8); break;
-		case RCNT3_TARGET: rcntWtarget(3, value); break;
-
-		case SIO_TXFIFO:
+		if ((sio_count == ArraySize(sio_buffer)-1) || (sio_buffer[sio_count-1] == '\n'))
 		{
-			// Terminate lines on CR or full buffers, and ignore \n's if the string contents
-			// are empty (otherwise terminate on \n too!)
-			if (( value == '\r' ) || ( sio_count == 1023 ) ||
-			     ( value == '\n' && sio_count != 0 ))
-			{
-				// Use "%s" below even though it feels indirect -- it's necessary to avoid
-				// errors if/when games use printf formatting control chars.
-
-				sio_buffer[sio_count] = 0;
-				Console.WriteLn( ConColor_EE, L"%s", ShiftJIS_ConvertString(sio_buffer).c_str() );
-				sio_count = 0;
-			}
-			else if( value != '\n' )
-			{
-				sio_buffer[sio_count++] = value;
-			}
+			sio_buffer[sio_count] = 0;
+			eeConLog( ShiftJIS_ConvertString(sio_buffer) );
+			sio_count = 0;
 		}
-		break;
-
-		//case 0x10003c02: //Tony Hawks Project 8 uses this
-		//	vif1Write32(mem & ~0x2, value << 16);
-		//	break;
-		case D0_CHCR + 1: // dma0 - vif0
-			DMA_LOG("VIF0dma EXECUTE, value=0x%x", value);
-			DmaExec8(dmaVIF0, mem, value);
-			break;
-
-		case D1_CHCR + 1: // dma1 - vif1
-			DMA_LOG("VIF1dma EXECUTE, value=0x%x", value);
-			DmaExec8(dmaVIF1, mem, value);
-			break;
-
-		case D2_CHCR + 1: // dma2 - gif
-			DMA_LOG("GSdma EXECUTE, value=0x%x", value);
-			DmaExec8(dmaGIF, mem, value);
-			break;
-
-		case D3_CHCR + 1: // dma3 - fromIPU
-			DMA_LOG("IPU0dma EXECUTE, value=0x%x", value);
-			DmaExec8(dmaIPU0, mem, value);
-			break;
-
-		case D4_CHCR + 1: // dma4 - toIPU
-			DMA_LOG("IPU1dma EXECUTE, value=0x%x", value);
-			DmaExec8(dmaIPU1, mem, value);
-			break;
-
-		case D5_CHCR + 1: // dma5 - sif0
-			DMA_LOG("SIF0dma EXECUTE, value=0x%x", value);
-//			if (value == 0) psxSu32(0x30) = 0x40000;
-			DmaExec8(dmaSIF0, mem, value);
-			break;
-
-		case D6_CHCR + 1: // dma6 - sif1
-			DMA_LOG("SIF1dma EXECUTE, value=0x%x", value);
-			DmaExec8(dmaSIF1, mem, value);
-			break;
-
-		case D7_CHCR + 1: // dma7 - sif2
-			DMA_LOG("SIF2dma EXECUTE, value=0x%x", value);
-			DmaExec8(dmaSIF2, mem, value);
-			break;
-
-		case D8_CHCR + 1: // dma8 - fromSPR
-			DMA_LOG("fromSPRdma8 EXECUTE, value=0x%x", value);
-			DmaExec8(dmaSPR0, mem, value);
-			break;
-
-		case D9_CHCR + 1: // dma9 - toSPR
-			DMA_LOG("toSPRdma8 EXECUTE, value=0x%x", value);
-			DmaExec8(dmaSPR1, mem, value);
-			break;
-		case D0_CHCR: // dma0 - vif0
-		case D1_CHCR: // dma1 - vif1
-		case D2_CHCR: // dma2 - gif
-		case D3_CHCR: // dma3 - fromIPU
-		case D4_CHCR: // dma4 - toIPU
-		case D5_CHCR: // dma5 - sif0
-		case D6_CHCR: // dma6 - sif1
-		case D7_CHCR: // dma7 - sif2
-		case D8_CHCR: // dma8 - fromSPR
-		case D9_CHCR: // dma9 - toSPR
-			//DevCon.Warning(L"8bit lower CHCR changed to %x from %x on %s DMA", value, psHu32(mem), ChcrName(mem));
-			psHu8(mem) = value;
-			break;
-
-		case D0_CHCR + 2: // dma0 - vif0
-		case D0_CHCR + 3: // dma0 - vif0
-		case D1_CHCR + 2: // dma1 - vif1
-		case D1_CHCR + 3: // dma1 - vif1
-		case D2_CHCR + 2: // dma2 - gif
-		case D2_CHCR + 3: // dma2 - gif
-		case D3_CHCR + 2: // dma3 - fromIPU
-		case D3_CHCR + 3: // dma3 - fromIPU
-		case D4_CHCR + 2: // dma4 - toIPU
-		case D4_CHCR + 3: // dma4 - toIPU
-		case D5_CHCR + 2: // dma5 - sif0
-		case D5_CHCR + 3: // dma5 - sif0
-		case D6_CHCR + 2: // dma6 - sif1
-		case D6_CHCR + 3: // dma6 - sif1
-		case D7_CHCR + 2: // dma7 - sif2
-		case D7_CHCR + 3: // dma7 - sif2
-		case D8_CHCR + 2: // dma8 - fromSPR
-		case D8_CHCR + 3: // dma8 - fromSPR
-		case D9_CHCR + 2: // dma9 - toSPR
-		case D9_CHCR + 3: // dma9 - toSPR
-			//DevCon.Warning(L"8bit CHCR TAG changed to %x from %x on %s DMA", value, psHu32(mem), ChcrName(mem & ~0xf));
-			psHu8(mem) = value;
-			break;
-
-		case DMAC_ENABLEW + 2:
-			oldvalue = psHu8(DMAC_ENABLEW + 2);
-			psHu8(DMAC_ENABLEW + 2) = value;
-			psHu8(DMAC_ENABLER + 2) = value;
-			if (((oldvalue & 0x1) == 1) && ((value & 0x1) == 0))
-			{
-				if (!QueuedDMA.empty()) StartQueuedDMA();
-			}
-			break;
-
-		case SBUS_F200: // SIF(?)
-			psHu8(mem) = value;
-			break;
-
-		case SBUS_F210:
-			psHu8(mem) = value;
-			break;
-
-		case SBUS_F220:
-			psHu8(mem) = value;
-			break;
-
-		case SBUS_F230:
-			psHu8(mem) = value;
-			break;
-
-		case SBUS_F240:
-			if (!(value & 0x100)) psHu32(mem) &= ~0x100;
-			break;
-
-		case SBUS_F250:
-			psHu8(mem) = value;
-			break;
-
-		case SBUS_F260:
-			psHu8(mem) = value;
-			break;
-
-		default:
-			pxAssert( (mem & 0xff0f) != 0xf200 );
-
-			switch(mem&~3) {
-				case SIO_ISR:
-				case 0x1000f410:
-				case MCH_RICM:
-					break;
-
-				default:
-					psHu8(mem) = value;
-			}
-			HW_LOG("Unknown Hardware write 8 at %x with value %x", mem, value);
-			break;
+		return;
 	}
-}
 
-__forceinline void hwWrite16(u32 mem, u16 value)
-{
-	if( mem >= IPU_CMD && mem < D0_CHCR )
-		Console.Warning( "hwWrite16 to %x", mem );
+	u32 merged = _hwRead32<page,false>(mem & ~0x03);
+	((u8*)&merged)[mem & 0x3] = value;
 
-	switch(mem)
-	{
-		case RCNT0_COUNT: rcntWcount(0, value); break;
-		case RCNT0_MODE: rcntWmode(0, value); break;
-		case RCNT0_TARGET: rcntWtarget(0, value); break;
-		case RCNT0_HOLD: rcntWhold(0, value); break;
-
-		case RCNT1_COUNT: rcntWcount(1, value); break;
-		case RCNT1_MODE: rcntWmode(1, value); break;
-		case RCNT1_TARGET: rcntWtarget(1, value); break;
-		case RCNT1_HOLD: rcntWhold(1, value); break;
-
-		case RCNT2_COUNT: rcntWcount(2, value); break;
-		case RCNT2_MODE: rcntWmode(2, value); break;
-		case RCNT2_TARGET: rcntWtarget(2, value); break;
-
-		case RCNT3_COUNT: rcntWcount(3, value); break;
-		case RCNT3_MODE: rcntWmode(3, value); break;
-		case RCNT3_TARGET: rcntWtarget(3, value); break;
-
-		case D0_CHCR: // dma0 - vif0
-			DMA_LOG("VIF0dma %lx", value);
-			DmaExec16(dmaVIF0, mem, value);
-			break;
-
-		case D1_CHCR: // dma1 - vif1 - chcr
-			DMA_LOG("VIF1dma CHCR %lx", value);
-			DmaExec16(dmaVIF1, mem, value);
-			break;
-
-#ifdef PCSX2_DEVBUILD
-		case D1_MADR: // dma1 - vif1 - madr
-			HW_LOG("VIF1dma Madr %lx", value);
-			psHu16(mem) = value;//dma1 madr
-			break;
-
-		case D1_QWC: // dma1 - vif1 - qwc
-			HW_LOG("VIF1dma QWC %lx", value);
-			psHu16(mem) = value;//dma1 qwc
-			break;
-
-		case D1_TADR: // dma1 - vif1 - tadr
-			HW_LOG("VIF1dma TADR %lx", value);
-			psHu16(mem) = value;//dma1 tadr
-			break;
-
-		case D1_ASR0: // dma1 - vif1 - asr0
-			HW_LOG("VIF1dma ASR0 %lx", value);
-			psHu16(mem) = value;//dma1 asr0
-			break;
-
-		case D1_ASR1: // dma1 - vif1 - asr1
-			HW_LOG("VIF1dma ASR1 %lx", value);
-			psHu16(mem) = value;//dma1 asr1
-			break;
-
-		case D1_SADR: // dma1 - vif1 - sadr
-			HW_LOG("VIF1dma SADR %lx", value);
-			psHu16(mem) = value;//dma1 sadr
-			break;
-#endif
-// ---------------------------------------------------
-
-		case D2_CHCR: // dma2 - gif
-			DMA_LOG("0x%8.8x hwWrite32: GSdma %lx", cpuRegs.cycle, value);
-			DmaExec16(dmaGIF, mem, value);
-			break;
-
-#ifdef PCSX2_DEVBUILD
-		case D2_MADR:
-		    psHu16(mem) = value;//dma2 madr
-			HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x",mem,value);
-		    break;
-
-		case D2_QWC:
-			psHu16(mem) = value;//dma2 qwc
-			HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x",mem,value);
-			break;
-
-		case D2_TADR:
-			psHu16(mem) = value;//dma2 taddr
-			HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x",mem,value);
-			break;
-
-		case D2_ASR0:
-			psHu16(mem) = value;//dma2 asr0
-			HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x",mem,value);
-			break;
-
-		case D2_ASR1:
-			psHu16(mem) = value;//dma2 asr1
-			HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x",mem,value);
-			break;
-
-		case D2_SADR:
-			psHu16(mem) = value;//dma2 saddr
-			HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x",mem,value);
-			break;
-#endif
-
-		case D3_CHCR: // dma3 - fromIPU
-			DMA_LOG("IPU0dma %lx", value);
-			DmaExec16(dmaIPU0, mem, value);
-			break;
-
-#ifdef PCSX2_DEVBUILD
-		case D3_MADR:
-	   		psHu16(mem) = value;//dma2 madr
-			HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x",mem,value);
-			break;
-
-		case D3_QWC:
-			psHu16(mem) = value;//dma2 madr
-			HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x",mem,value);
-			break;
-
-		case D3_TADR:
-			psHu16(mem) = value;//dma2 tadr
-			HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x",mem,value);
-			break;
-
-		case D3_SADR:
-			psHu16(mem) = value;//dma2 saddr
-			HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x",mem,value);
-			break;
-#endif
-
-		case D4_CHCR: // dma4 - toIPU
-			DMA_LOG("IPU1dma %lx", value);
-			DmaExec16(dmaIPU1, mem, value);
-			break;
-
-#ifdef PCSX2_DEVBUILD
-		case D4_MADR:
-			psHu16(mem) = value;//dma2 madr
-			HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x",mem,value);
-       		break;
-
-		case D4_QWC:
-			psHu16(mem) = value;//dma2 madr
-			HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x",mem,value);
-       		break;
-
-		case D4_TADR:
-			psHu16(mem) = value;//dma2 tadr
-			HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x",mem,value);
-			break;
-
-		case D4_SADR:
-			psHu16(mem) = value;//dma2 saddr
-			HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x",mem,value);
-			break;
-#endif
-		case D5_CHCR: // dma5 - sif0
-			DMA_LOG("SIF0dma %lx", value);
-			DmaExec16(dmaSIF0, mem, value);
-			break;
-
-		case D6_CHCR: // dma6 - sif1
-			DMA_LOG("SIF1dma %lx", value);
-			DmaExec16(dmaSIF1, mem, value);
-			break;
-
-		// Given the other values here, perhaps something like this is in order?
-		/*case 0x1000C402: // D6_CHCR + 2
-			//?
-			break;*/
-
-#ifdef PCSX2_DEVBUILD
-		case D6_MADR: // dma6 - sif1 - madr
-			HW_LOG("SIF1dma MADR = %lx", value);
-			psHu16(mem) = value;
-			break;
-
-		case D6_QWC: // dma6 - sif1 - qwc
-			HW_LOG("SIF1dma QWC = %lx", value);
-			psHu16(mem) = value;
-			break;
-
-		case D6_TADR: // dma6 - sif1 - tadr
-			HW_LOG("SIF1dma TADR = %lx", value);
-			psHu16(mem) = value;
-			break;
-#endif
-
-		case D7_CHCR: // dma7 - sif2
-			DMA_LOG("SIF2dma %lx", value);
-			DmaExec16(dmaSIF2, mem, value);
-			break;
-
-		case D8_CHCR: // dma8 - fromSPR
-			DMA_LOG("fromSPRdma %lx", value);
-			DmaExec16(dmaSPR0, mem, value);
-			break;
-
-		case D9_CHCR: // dma9 - toSPR
-			DMA_LOG("toSPRdma %lx", value);
-			DmaExec16(dmaSPR1, mem, value);
-			break;
-
-		case D0_CHCR + 2: // dma0 - vif0
-		case D1_CHCR + 2: // dma1 - vif1
-		case D2_CHCR + 2: // dma2 - gif
-		case D3_CHCR + 2: // dma3 - fromIPU
-		case D4_CHCR + 2: // dma4 - toIPU
-		case D5_CHCR + 2: // dma5 - sif0
-		case D6_CHCR + 2: // dma6 - sif1
-		case D7_CHCR + 2: // dma7 - sif2
-		case D8_CHCR + 2: // dma8 - fromSPR
-		case D9_CHCR + 2: // dma9 - toSPR
-			//DevCon.Warning(L"16bit CHCR TAG changed to %x from %x on %s DMA", value, psHu32(mem), ChcrName(mem & ~0xf));
-			psHu16(mem) = value;
-			break;
-
-		case DMAC_ENABLEW + 2:
-			oldvalue = psHu8(DMAC_ENABLEW + 2);
-			psHu16(DMAC_ENABLEW + 2) = value;
-			psHu16(DMAC_ENABLER + 2) = value;
-			if (((oldvalue & 0x1) == 1) && ((value & 0x1) == 0))
-			{
-				if (!QueuedDMA.empty()) StartQueuedDMA();
-			}
-			break;
-
-		case SIO_ISR:
-		case SIO_ISR + 2:
-		case 0x1000f410:
-		case 0x1000f410 + 2:
-		case MCH_RICM:
-		case MCH_RICM + 2:
-			break;
-
-		case SBUS_F200:
-			psHu16(mem) = value;
-			break;
-
-		case SBUS_F210:
-			psHu16(mem) = value;
-			break;
-
-		case SBUS_F220:
-			psHu16(mem) |= value;
-			break;
-
-		case SBUS_F230:
-			psHu16(mem) &= ~value;
-			break;
-
-		case SBUS_F240:
-			if (!(value & 0x100))
-				psHu16(mem) &= ~0x100;
-			else
-				psHu16(mem) |= 0x100;
-			break;
-
-		case SBUS_F250:
-			psHu16(mem) = value;
-			break;
-
-		case SBUS_F260:
-			psHu16(mem) = 0;
-			break;
-
-		default:
-			psHu16(mem) = value;
-			UnknownHW_LOG("Unknown Hardware write 16 at %x with value %x",mem,value);
-	}
+	_hwWrite32<page>(mem & ~0x03, merged);
 }
 
-// Page 0 of HW memory houses registers for Counters 0 and 1
-void __fastcall hwWrite32_page_00( u32 mem, u32 value )
+template< uint page >
+void __fastcall hwWrite8(u32 mem, u8 value)
 {
-	mem &= 0xffff;
-	switch (mem)
-	{
-		case 0x000: rcntWcount(0, value); return;
-		case 0x010: rcntWmode(0, value); return;
-		case 0x020: rcntWtarget(0, value); return;
-		case 0x030: rcntWhold(0, value); return;
-
-		case 0x800: rcntWcount(1, value); return;
-		case 0x810: rcntWmode(1, value); return;
-		case 0x820: rcntWtarget(1, value); return;
-		case 0x830: rcntWhold(1, value); return;
-	}
-
-	*((u32*)&PS2MEM_HW[mem]) = value;
+	eeHwTraceLog( mem, value, false );
+	_hwWrite8<page>(mem, value);
 }
 
-// Page 1 of HW memory houses registers for Counters 2 and 3
-void __fastcall hwWrite32_page_01( u32 mem, u32 value )
+template< uint page >
+void __fastcall _hwWrite16(u32 mem, u16 value)
 {
-	mem &= 0xffff;
-	switch (mem)
-	{
-		case 0x1000: rcntWcount(2, value); return;
-		case 0x1010: rcntWmode(2, value); return;
-		case 0x1020: rcntWtarget(2, value); return;
-
-		case 0x1800: rcntWcount(3, value); return;
-		case 0x1810: rcntWmode(3, value); return;
-		case 0x1820: rcntWtarget(3, value); return;
-	}
+	pxAssume( (mem & 0x01) == 0 );
 
-	*((u32*)&PS2MEM_HW[mem]) = value;
-}
+	u32 merged = _hwRead32<page,false>(mem & ~0x03);
+	((u16*)&merged)[(mem>>1) & 0x1] = value;
 
-// page 2 is the IPU register space!
-void __fastcall hwWrite32_page_02( u32 mem, u32 value )
-{
-	ipuWrite32(mem, value);
+	hwWrite32<page>(mem & ~0x03, merged);
 }
 
-// Page 3 contains writes to vif0 and vif1 registers, plus some GIF stuff!
-void __fastcall hwWrite32_page_03( u32 mem, u32 value )
+template< uint page >
+void __fastcall hwWrite16(u32 mem, u16 value)
 {
-	if (mem >= VIF0_STAT)
-	{
-		if(mem < VIF1_STAT)
-			vif0Write32(mem, value);
-		else
-			vif1Write32(mem, value);
-		return;
-	}
-
-	switch (mem)
-	{
-		case GIF_CTRL:
-			psHu32(mem) = value & 0x8;
-
-			if (value & 0x1)
-				gsGIFReset();
-			else if ( value & 8 )
-				gifRegs->stat.PSE = true;
-			else
-				gifRegs->stat.PSE = false;
-		break;
-
-		case GIF_MODE:
-		{
-			// need to set GIF_MODE (hamster ball)
-			gifRegs->mode.write(value);
-
-			// set/clear bits 0 and 2 as per the GIF_MODE value.
-            const u32 bitmask = GIF_MODE_M3R | GIF_MODE_IMT;
-			psHu32(GIF_STAT) &= ~bitmask;
-			psHu32(GIF_STAT) |= (u32)value & bitmask;
-
-		}
-		break;
-
-		case GIF_STAT: // stat is readonly
-			DevCon.Warning("*PCSX2* GIFSTAT write value = 0x%x (readonly, ignored)", value);
-		break;
-
-		default:
-			psHu32(mem) = value;
-	}
+	eeHwTraceLog( mem, value, false );
+	_hwWrite16<page>(mem, value);
 }
 
-void __fastcall hwWrite32_page_0B( u32 mem, u32 value )
+template<uint page>
+void __fastcall _hwWrite64( u32 mem, const mem64_t* srcval )
 {
-	// Used for developer logging -- optimized away in Public Release.
-	const char* regName = "Unknown";
-
-	switch( mem )
-	{
-		case D3_CHCR: // dma3 - fromIPU
-			DMA_LOG("IPU0dma EXECUTE, value=0x%x\n", value);
-			DmaExec(dmaIPU0, mem, value);
-			return;
-
-		case D3_MADR: regName = "IPU0DMA_MADR"; break;
-		case D3_QWC: regName = "IPU0DMA_QWC"; break;
-		case D3_TADR: regName = "IPU0DMA_TADR"; break;
-		case D3_SADR: regName = "IPU0DMA_SADDR"; break;
-
-		//------------------------------------------------------------------
-
-		case D4_CHCR: // dma4 - toIPU
-			DMA_LOG("IPU1dma EXECUTE, value=0x%x\n", value);
-			DmaExec(dmaIPU1, mem, value);
-			return;
-
-		case D4_MADR: regName = "IPU1DMA_MADR"; break;
-		case D4_QWC: regName = "IPU1DMA_QWC"; break;
-		case D4_TADR: regName = "IPU1DMA_TADR"; break;
-		case D4_SADR: regName = "IPU1DMA_SADDR"; break;
-	}
-
-	HW_LOG( "Hardware Write32 at 0x%x (%s), value=0x%x", mem, regName, value );
-	psHu32(mem) = value;
-}
+	pxAssume( (mem & 0x07) == 0 );
 
+	// * Only the IPU has true 64 bit registers.
+	// * FIFOs have 128 bit registers that are probably zero-fill.
+	// * All other registers likely disregard the upper 32-bits and simply act as normal
+	//   32-bit writes.
 
-
-void __fastcall hwWrite32_page_0E( u32 mem, u32 value )
-{
-	switch (mem)
+	switch (page)
 	{
-		case DMAC_CTRL:
-		{
-			u32 oldvalue = psHu32(mem);
-
-			HW_LOG("DMAC_CTRL Write 32bit %x", value);
+		case 0x02:
+			if (!ipuWrite64(mem, *srcval)) return;
+		break;
 
-			psHu32(mem) = value;
-			//Check for DMAS that were started while the DMAC was disabled
-			if (((oldvalue & 0x1) == 0) && ((value & 0x1) == 1))
-			{
-				if (!QueuedDMA.empty()) StartQueuedDMA();
-			}
-			break;
+		case 0x04:
+		case 0x05:
+		case 0x06:
+		case 0x07:
+		{
+			DevCon.WriteLn( Color_Cyan, "Writing 64-bit FIFO data (zero-extended to 128 bits)" );
+
+			u128 zerofill = u128::From32(0);
+			zerofill._u64[(mem >> 3) & 0x01] = *srcval;
+			hwWrite128<page>(mem & ~0x0f, &zerofill);
 		}
-
-		case DMAC_STAT:
-			HW_LOG("DMAC_STAT Write 32bit %x", value);
-
-			// lower 16 bits: clear on 1
-			// upper 16 bits: reverse on 1
-
-			psHu16(0xe010) &= ~(value & 0xffff);
-			psHu16(0xe012) ^= (u16)(value >> 16);
-
-			cpuTestDMACInts();
-			break;
-
-		default:
-			psHu32(mem) = value;
-			break;
-	}
-}
-
-void __fastcall hwWrite32_page_0F( u32 mem, u32 value )
-{
-	// Shift the middle 8 bits (bits 4-12) into the lower 8 bits.
-	// This helps the compiler optimize the switch statement into a lookup table. :)
-
-#define HELPSWITCH(m) (((m)>>4) & 0xff)
-
-	switch( HELPSWITCH(mem) )
-	{
-		case HELPSWITCH(INTC_STAT):
-			HW_LOG("INTC_STAT Write 32bit %x", value);
-			psHu32(INTC_STAT) &= ~value;
-			//cpuTestINTCInts();
-			break;
-
-		case HELPSWITCH(INTC_MASK):
-			HW_LOG("INTC_MASK Write 32bit %x", value);
-			psHu32(INTC_MASK) ^= (u16)value;
-			cpuTestINTCInts();
-			break;
-
-		//------------------------------------------------------------------
-		case HELPSWITCH(MCH_RICM)://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;	// if SIO repeater is cleared, reset sdevid
-			psHu32(mem) = value & ~0x80000000;	//kill the busy bit
-			break;
-
-		case HELPSWITCH(SBUS_F200):
-			psHu32(mem) = value;
-			break;
-
-		case HELPSWITCH(SBUS_F220):
-			psHu32(mem) |= value;
-			break;
-
-		case HELPSWITCH(SBUS_F230):
-			psHu32(mem) &= ~value;
-			break;
-
-		case HELPSWITCH(SBUS_F240):
-			if(!(value & 0x100))
-				psHu32(mem) &= ~0x100;
-			else
-				psHu32(mem) |= 0x100;
-			break;
-
-		case HELPSWITCH(SBUS_F260):
-			psHu32(mem) = 0;
-			break;
-
-		case HELPSWITCH(MCH_DRD)://MCH_DRD:
-			psHu32(mem) = value;
-			break;
-
-		case HELPSWITCH(DMAC_ENABLEW):
-			HW_LOG("DMAC_ENABLEW Write 32bit %lx", value);
-			oldvalue = psHu8(DMAC_ENABLEW + 2);
-			psHu32(DMAC_ENABLEW) = value;
-			psHu32(DMAC_ENABLER) = value;
-			if (((oldvalue & 0x1) == 1) && (((value >> 16) & 0x1) == 0))
-			{
-				if (!QueuedDMA.empty()) StartQueuedDMA();
-			}
-			break;
-
-		//------------------------------------------------------------------
-		case HELPSWITCH(SIO_ISR):
-		case HELPSWITCH(0x1000f410):
-			UnknownHW_LOG("Unknown Hardware write 32 at %x with value %x (%x)", mem, value, cpuRegs.CP0.n.Status.val);
-			break;
-
+		return;
+		
 		default:
-			psHu32(mem) = value;
-	}
-}
-
-void __fastcall hwWrite32_generic( u32 mem, u32 value )
-{
-	// Used for developer logging -- optimized away in Public Release.
-	const char* regName = "Unknown";
-
-	switch (mem)
-	{
-		case D0_CHCR: // dma0 - vif0
-			DMA_LOG("VIF0dma EXECUTE, value=0x%x", value);
-			DmaExec(dmaVIF0, mem, value);
-			return;
-
-//------------------------------------------------------------------
-		case D1_CHCR: // dma1 - vif1 - chcr
-			DMA_LOG("VIF1dma EXECUTE, value=0x%x", value);
-			DmaExec(dmaVIF1, mem, value);
-			return;
-
-		case D1_MADR: regName = "VIF1dma MADR"; break;
-		case D1_QWC: regName = "VIF1dma QWC"; break;
-		case D1_TADR: regName = "VIF1dma TADR"; break;
-		case D1_ASR0: regName = "VIF1dma ASR0"; break;
-		case D1_ASR1: regName = "VIF1dma ASR1"; break;
-		case D1_SADR: regName = "VIF1dma SADR"; break;
-
-//------------------------------------------------------------------
-		case D2_CHCR: // dma2 - gif
-			DMA_LOG("GIFdma EXECUTE, value=0x%x", value);
-			DmaExec(dmaGIF, mem, value);
-			return;
-
-		case D2_MADR: regName = "GIFdma MADR"; break;
-		case D2_QWC: regName = "GIFdma QWC"; break;
-		case D2_TADR: regName = "GIFdma TADDR"; break;
-		case D2_ASR0: regName = "GIFdma ASR0"; break;
-		case D2_ASR1: regName = "GIFdma ASR1"; break;
-		case D2_SADR: regName = "GIFdma SADDR"; break;
-
-//------------------------------------------------------------------
-		case D5_CHCR: // dma5 - sif0
-			DMA_LOG("SIF0dma EXECUTE, value=0x%x", value);
-			DmaExec(dmaSIF0, mem, value);
-			return;
-//------------------------------------------------------------------
-		case D6_CHCR: // dma6 - sif1
-			DMA_LOG("SIF1dma EXECUTE, value=0x%x", value);
-			DmaExec(dmaSIF1, mem, value);
-			return;
-
-		case D6_MADR: regName = "SIF1dma MADR"; break;
-		case D6_QWC: regName = "SIF1dma QWC"; break;
-		case D6_TADR: regName = "SIF1dma TADR"; break;
-
-//------------------------------------------------------------------
-		case D7_CHCR: // dma7 - sif2
-			DMA_LOG("SIF2dma EXECUTE, value=0x%x", value);
-			DmaExec(dmaSIF2, mem, value);
-			return;
-//------------------------------------------------------------------
-		case D8_CHCR: // dma8 - fromSPR
-			DMA_LOG("SPR0dma EXECUTE (fromSPR), value=0x%x", value);
-			DmaExec(dmaSPR0, mem, value);
-			return;
-//------------------------------------------------------------------
-		case D9_CHCR: // dma9 - toSPR
-			DMA_LOG("SPR1dma EXECUTE (toSPR), value=0x%x", value);
-			DmaExec(dmaSPR1, mem, value);
-			return;
+			// disregard everything except the lower 32 bits.
+			// ... and skip the 64 bit writeback since the 32-bit one will suffice.
+			hwWrite32<page>( mem, ((u32*)srcval)[0] );
+		return;
 	}
-	HW_LOG( "Hardware Write32 at 0x%x (%s), value=0x%x", mem, regName, value );
-	psHu32(mem) = value;
-}
 
-/////////////////////////////////////////////////////////////////////////
-// HW Write 64 bit
-
-// Page 0 of HW memory houses registers for Counters 0 and 1
-void __fastcall hwWrite64_page_00( u32 mem, const mem64_t* srcval )
-{
-	hwWrite32_page_00( mem, (u32)*srcval );		// just ignore upper 32 bits.
 	psHu64(mem) = *srcval;
 }
 
-// Page 1 of HW memory houses registers for Counters 2 and 3
-void __fastcall hwWrite64_page_01( u32 mem, const mem64_t* srcval )
+template<uint page>
+void __fastcall hwWrite64( u32 mem, const mem64_t* srcval )
 {
-	hwWrite32_page_01( mem, (u32)*srcval );		// just ignore upper 32 bits.
-	psHu64(mem) = *srcval;
+	eeHwTraceLog( mem, *srcval, false );
+	_hwWrite64<page>(mem, srcval);
 }
 
-void __fastcall hwWrite64_page_02( u32 mem, const mem64_t* srcval )
+template< uint page >
+void __fastcall _hwWrite128(u32 mem, const mem128_t* srcval)
 {
-	//hwWrite64( mem, *srcval );  return;
-	ipuWrite64( mem, *srcval );
-}
+	pxAssume( (mem & 0x0f) == 0 );
 
-void __fastcall hwWrite64_page_03( u32 mem, const mem64_t* srcval )
-{
-	//hwWrite64( mem, *srcval ); return;
-	const u64 value = *srcval;
+	// FIFOs are the only "legal" 128 bit registers.  Handle them first.
+	// all other registers fall back on the 64-bit handler (and from there
+	// most of them fall back to the 32-bit handler).
 
-	if (mem >= VIF0_STAT)
+	switch (page)
 	{
-		if (mem < VIF1_STAT)
-			vif0Write32(mem, value);
-		else
-			vif1Write32(mem, value);
+		case 0x04:
+			WriteFIFO_VIF0(srcval);
 		return;
-	}
-
-	switch (mem)
-	{
-		case GIF_CTRL:
-			DevCon.WriteLn("GIF_CTRL write 64", value);
-			psHu32(mem) = value & 0x8;
-			if(value & 0x1)
-				gsGIFReset();
-			else
-			{
-				if( value & 8 )
-					gifRegs->stat.PSE = true;
-				else
-					gifRegs->stat.PSE = false;
-			}
-			break;
-
-		case GIF_MODE:
-		{
-			// set/clear bits 0 and 2 as per the GIF_MODE value.
-			const u32 bitmask = GIF_MODE_M3R | GIF_MODE_IMT;
-
-			Console.WriteLn("GIFMODE64 %x", value);
-
-			psHu64(GIF_MODE) = value;
-			psHu32(GIF_STAT) &= ~bitmask;
-			psHu32(GIF_STAT) |= (u32)value & bitmask;
-			break;
-		}
-
-		case GIF_STAT: // stat is readonly
-			break;
-	}
-}
 
-void __fastcall hwWrite64_page_0E( u32 mem, const mem64_t* srcval )
-{
-	//hwWrite64( mem, *srcval ); return;
-
-	const u64 value = *srcval;
-
-	switch (mem)
-	{
-		case DMAC_CTRL:
-		{
-			u32 oldvalue = psHu32(mem);
-			psHu64(mem) = value;
+		case 0x05:
+			WriteFIFO_VIF1(srcval);
+		return;
 
-			HW_LOG("DMAC_CTRL Write 64bit %x", value);
+		case 0x06:
+			WriteFIFO_GIF(srcval);
+		return;
 
-			if (((oldvalue & 0x1) == 0) && ((value & 0x1) == 1))
+		case 0x07:
+			if (mem & 0x10)
 			{
-				if (!QueuedDMA.empty()) StartQueuedDMA();
+				WriteFIFO_IPUin(srcval);
 			}
-			break;
-		}
-
-		case DMAC_STAT:
-			HW_LOG("DMAC_STAT Write 64bit %x", value);
-
-			// lower 16 bits: clear on 1
-			// upper 16 bits: reverse on 1
-
-			psHu16(0xe010) &= ~(value & 0xffff);
-			psHu16(0xe012) ^= (u16)(value >> 16);
-
-			cpuTestDMACInts();
-			break;
+			else
+			{
+				// [Ps2Confirm] Most likely writes to IPUout will be silently discarded.  A test
+				// to confirm such would be easy -- just dump some data to FIFO_IPUout and see
+				// if the program causes BUSERR or something on the PS2.
 
-		default:
-			psHu64(mem) = value;
-			break;
+				//WriteFIFO_IPUout(srcval);
+			}
+				
+		return;
 	}
-}
 
-void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval )
-{
-	const u64 value = *srcval;
+	// All upper bits of all non-FIFO 128-bit HW writes are almost certainly disregarded. --air
+	hwWrite64<page>(mem, (mem64_t*)srcval);
 
-	switch (mem)
-	{
-		case D2_CHCR: // dma2 - gif
-			DMA_LOG("0x%8.8x hwWrite64: GSdma %x", cpuRegs.cycle, value);
-			DmaExec(dmaGIF, mem, value);
-			break;
-
-		case INTC_STAT:
-			HW_LOG("INTC_STAT Write 64bit %x", (u32)value);
-			psHu32(INTC_STAT) &= ~value;
-			//cpuTestINTCInts();
-			break;
-
-		case INTC_MASK:
-			HW_LOG("INTC_MASK Write 64bit %x", (u32)value);
-			psHu32(INTC_MASK) ^= (u16)value;
-			cpuTestINTCInts();
-			break;
-
-		case SIO_ISR:
-		case 0x1000f410:
-		case MCH_RICM:
-			break;
-
-		case DMAC_ENABLEW: // DMAC_ENABLEW
-			oldvalue = psHu8(DMAC_ENABLEW + 2);
-			psHu32(DMAC_ENABLEW) = value;
-			psHu32(DMAC_ENABLER) = value;
-			if (((oldvalue & 0x1) == 1) && (((value >> 16) & 0x1) == 0))
-			{
-				if (!QueuedDMA.empty()) StartQueuedDMA();
-			}
-		break;
-
-		default:
-			psHu64(mem) = value;
-			UnknownHW_LOG("Unknown Hardware write 64 at %x with value %x (status=%x)",mem,value, cpuRegs.CP0.n.Status.val);
-		break;
-	}
+	//CopyQWC(&psHu128(mem), srcval);
 }
 
-/////////////////////////////////////////////////////////////////////////
-// HW Write 128 bit
-
-void __fastcall hwWrite128_generic(u32 mem, const mem128_t *srcval)
+template< uint page >
+void __fastcall hwWrite128(u32 mem, const mem128_t* srcval)
 {
-	//hwWrite128( mem, srcval ); return;
-
-	switch (mem)
-	{
-		case INTC_STAT:
-			HW_LOG("INTC_STAT Write 64bit %x", (u32)srcval[0]);
-			psHu32(INTC_STAT) &= ~srcval[0];
-			//cpuTestINTCInts();
-		break;
-
-		case INTC_MASK:
-			HW_LOG("INTC_MASK Write 64bit %x", (u32)srcval[0]);
-			psHu32(INTC_MASK) ^= (u16)srcval[0];
-			cpuTestINTCInts();
-		break;
-
-		case DMAC_ENABLEW: // DMAC_ENABLEW
-			oldvalue = psHu8(DMAC_ENABLEW + 2);
-			psHu32(DMAC_ENABLEW) = srcval[0];
-			psHu32(DMAC_ENABLER) = srcval[0];
-			if (((oldvalue & 0x1) == 1) && (((srcval[0] >> 16) & 0x1) == 0))
-			{
-				if (!QueuedDMA.empty()) StartQueuedDMA();
-			}
-		break;
-
-		case SIO_ISR:
-		case 0x1000f410:
-		case MCH_RICM:
-			break;
-
-		default:
-			psHu64(mem  ) = srcval[0];
-			psHu64(mem+8) = srcval[1];
-
-			UnknownHW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)", mem, srcval[1], srcval[0], cpuRegs.CP0.n.Status.val);
-		break;
-	}
-}
+	eeHwTraceLog( mem, *srcval, false );
+	_hwWrite128<page>(mem, srcval);
+}
+
+#define InstantizeHwWrite(pageidx) \
+	template void __fastcall hwWrite8<pageidx>(u32 mem, mem8_t value); \
+	template void __fastcall hwWrite16<pageidx>(u32 mem, mem16_t value); \
+	template void __fastcall hwWrite32<pageidx>(u32 mem, mem32_t value); \
+	template void __fastcall hwWrite64<pageidx>(u32 mem, const mem64_t* srcval); \
+	template void __fastcall hwWrite128<pageidx>(u32 mem, const mem128_t* srcval);
+
+InstantizeHwWrite(0x00);	InstantizeHwWrite(0x08);
+InstantizeHwWrite(0x01);	InstantizeHwWrite(0x09);
+InstantizeHwWrite(0x02);	InstantizeHwWrite(0x0a);
+InstantizeHwWrite(0x03);	InstantizeHwWrite(0x0b);
+InstantizeHwWrite(0x04);	InstantizeHwWrite(0x0c);
+InstantizeHwWrite(0x05);	InstantizeHwWrite(0x0d);
+InstantizeHwWrite(0x06);	InstantizeHwWrite(0x0e);
+InstantizeHwWrite(0x07);	InstantizeHwWrite(0x0f);

 

  ViewVC Help
Powered by ViewVC 1.1.22