Commit

superfury committed dda2df9

- Improved BIU handling of byte/word/dword fetches from memory, by detecting the point at which the BIU splits the word/dword access with alignment while processing, using a simple address mask to detect break-during-transfer instead of a precalculated break bases on the base address, improving compatibility with 32-bit buses and 16-bit buses accessing 32-bit quantities from memory.

Comments (0)

Files changed (2)

File UniPCemu/cpu/biu.c Modified

View file
  • Ignore whitespace
  • Hide word diff
 BIU_type BIU[MAXCPUS]; //All possible BIUs!
 
 extern byte PIQSizes[2][NUMCPUS]; //The PIQ buffer sizes!
-
+extern byte BUSmasks[2][NUMCPUS]; //The bus masks, for applying 8/16/32-bit data buses to the memory accesses!
 byte CPU_databussize = 0; //0=16/32-bit bus! 1=8-bit bus when possible (8088/80188) or 16-bit when possible(286+)!
+byte CPU_databusmask = 0; //The mask from the BUSmasks lookup table!
 
 extern byte cpudebugger; //To debug the CPU?
 
 	{
 		BIU[activeCPU].PIQ = allocfifobuffer(PIQSizes[CPU_databussize][EMULATED_CPU],0); //Our PIQ we use!
 	}
+	CPU_databusmask = BUSmasks[CPU_databussize][EMULATED_CPU]; //Our data bus mask we use for splitting memory chunks!
 	BIU[activeCPU].requests = allocfifobuffer(20,0); //Our request buffer to use(1 64-bit entry being 2 32-bit entries, for 2 64-bit entries(payload) and 1 32-bit entry(the request identifier))!
 	BIU[activeCPU].responses = allocfifobuffer(sizeof(uint_32)<<1,0); //Our response buffer to use(1 64-bit entry as 2 32-bit entries)!
 	BIU[activeCPU].ready = 1; //We're ready to be used!
 byte BIU_access_writeshift[4] = {32,40,48,56}; //Shift to get the result byte to write to memory!
 byte BIU_access_readshift[4] = {0,8,16,24}; //Shift to put the result byte in the result!
 
-OPTINLINE byte BIU_isfulltransfer()
-{
-	INLINEREGISTER byte result;
-	result = 0; //Default: byte transfer!
-	if ((BIU[activeCPU].currentrequest&REQUEST_16BIT) && ((BIU[activeCPU].currentaddress&1)==0)) //Aligned 16-bit access?
-	{
-		if ((EMULATED_CPU>=CPU_80386) || ((EMULATED_CPU<=CPU_80286) && (CPU_databussize==0))) //16-bit+ bus available?
-		{
-			result = 1; //Start a full transfer this very clock!
-		}
-	}
-	else if ((BIU[activeCPU].currentrequest&REQUEST_32BIT) && ((BIU[activeCPU].currentaddress&3)==0)) //Aligned 32-bit access?
-	{
-		if ((EMULATED_CPU>=CPU_80386) && (CPU_databussize==0)) //32-bit processor with 32-bit bus?
-		{
-			result = 1; //Start a full transfer this very clock!
-		}
-		else if (EMULATED_CPU>=CPU_80386) //32-bit processor with 16-bit data bus?
-		{
-			result = 2; //Start a full transfer, broken in half(two 16-bit accesses)!
-		}
-	}
-	else if ((BIU[activeCPU].currentrequest&REQUEST_32BIT) && ((BIU[activeCPU].currentaddress&1)==0)) //Word-Aligned 32-bit access, but not 32-bit aligned? Break up into word accesses, when possible!
-	{
-		if (EMULATED_CPU>=CPU_80386) //32-bit processor with 16-bit data bus at least?
-		{
-			result = 2; //Start a full transfer, broken in half(two 16-bit accesses)!
-		}
-	}
-	return result; //Give the result!
-}
-
 //Linear memory access for the CPU through the Memory Unit!
 extern byte MMU_logging; //Are we logging?
 extern MMU_type MMU; //MMU support!
 	return 0; //We're fetched!
 }
 
-byte fulltransfer=0; //Are we to fully finish the transfer in one go?
 OPTINLINE byte BIU_processRequests(byte memory_waitstates)
 {
 	if (BIU[activeCPU].currentrequest) //Do we have a pending request we're handling? This is used for 16-bit and 32-bit requests!
 				{
 					BIU[activeCPU].currentrequest += REQUEST_SUB1; //Request next 8-bit half next(high byte)!
 					++BIU[activeCPU].currentaddress; //Next address!
-					if ((fulltransfer==2) && ((BIU[activeCPU].currentaddress&3)==2)) return 1; //Finished 16-bit half of a split 32-bit transfer?
-					if (fulltransfer) goto fulltransferMMUread;
+					if (unlikely((BIU[activeCPU].currentaddress&CPU_databusmask)==0)) return 1; //Handled, but broken up at this point due to the data bus not supporting transferring the rest of the word in one go!
+					goto fulltransferMMUread;
 				}
 				return 1; //Handled!
 				break;
 				{
 					BIU[activeCPU].currentrequest += REQUEST_SUB1; //Request next 8-bit half next(high byte)!
 					++BIU[activeCPU].currentaddress; //Next address!
-					if ((fulltransfer==2) && ((BIU[activeCPU].currentaddress&3)==2)) return 1; //Finished 16-bit half of a split 32-bit transfer?
-					if (fulltransfer) goto fulltransferMMUwrite;
+					if (unlikely((BIU[activeCPU].currentaddress&CPU_databusmask)==0)) return 1; //Handled, but broken up at this point due to the data bus not supporting transferring the rest of the word in one go!
+					goto fulltransferMMUwrite;
 				}
 				return 1; //Handled!
 				break;
 				{
 					BIU[activeCPU].currentrequest += REQUEST_SUB1; //Request next 8-bit half next(high byte)!
 					++BIU[activeCPU].currentaddress; //Next address!
-					if ((fulltransfer==2) && ((BIU[activeCPU].currentaddress&3)==2)) return 1; //Finished 16-bit half of a split 32-bit transfer?
-					if (fulltransfer) goto fulltransferIOread;
+					if (unlikely((BIU[activeCPU].currentaddress&CPU_databusmask)==0)) return 1; //Handled, but broken up at this point due to the data bus not supporting transferring the rest of the word in one go!
+					goto fulltransferIOread;
 				}
 				return 1; //Handled!
 				break;
 				{
 					BIU[activeCPU].currentrequest += REQUEST_SUB1; //Request next 8-bit half next(high byte)!
 					++BIU[activeCPU].currentaddress; //Next address!
-					if ((fulltransfer==2) && ((BIU[activeCPU].currentaddress&3)==2)) return 1; //Finished 16-bit half of a split 32-bit transfer?
-					if (fulltransfer) goto fulltransferIOwrite;
+					if (unlikely((BIU[activeCPU].currentaddress&CPU_databusmask)==0)) return 1; //Handled, but broken up at this point due to the data bus not supporting transferring the rest of the word in one go!
+					goto fulltransferIOwrite;
 				}
 				return 1; //Handled!
 				break;
 	{
 		if (BIU_readRequest(&BIU[activeCPU].currentrequest,&BIU[activeCPU].currentpayload[0],&BIU[activeCPU].currentpayload[1])) //Read the request, if available!
 		{
-			fulltransfer = 0; //Init full transfer flag!
 			switch (BIU[activeCPU].currentrequest&REQUEST_TYPEMASK) //What kind of request?
 			{
 				//Memory operations!
 					}
 					else
 					{
-						fulltransfer = BIU_isfulltransfer(); //Are we a full transfer?
 						++BIU[activeCPU].currentaddress; //Next address!
-						if (fulltransfer) goto fulltransferMMUread; //Start Full transfer, when available?
+						if (unlikely((BIU[activeCPU].currentaddress&CPU_databusmask)==0)) return 1; //Handled, but broken up at this point due to the data bus not supporting transferring the rest of the word in one go!
+						goto fulltransferMMUread; //Start Full transfer, when available?
 					}
 					return 1; //Handled!
 					break;
 					else //Busy request?
 					{
 						BIU_directwb((BIU[activeCPU].currentpayload[0]&0xFFFFFFFF),(byte)((BIU[activeCPU].currentpayload[0]>>BIU_access_writeshift[0])&0xFF),0); //Write directly to memory now!
-						fulltransfer = BIU_isfulltransfer(); //Are we a full transfer?
 						++BIU[activeCPU].currentaddress; //Next address!
-						if (fulltransfer) goto fulltransferMMUwrite; //Start Full transfer, when available?
+						if (unlikely((BIU[activeCPU].currentaddress&CPU_databusmask)==0)) return 1; //Handled, but broken up at this point due to the data bus not supporting transferring the rest of the word in one go!
+						goto fulltransferMMUwrite; //Start Full transfer, when available?
 					}
 					return 1; //Handled!
 					break;
 					}
 					else
 					{
-						fulltransfer = BIU_isfulltransfer(); //Are we a full transfer?
 						++BIU[activeCPU].currentaddress; //Next address!
-						if (fulltransfer) goto fulltransferIOread; //Start Full transfer, when available?
+						if (unlikely((BIU[activeCPU].currentaddress&CPU_databusmask)==0)) return 1; //Handled, but broken up at this point due to the data bus not supporting transferring the rest of the word in one go!
+						goto fulltransferIOread; //Start Full transfer, when available?
 					}
 					return 1; //Handled!
 					break;
 					}
 					else
 					{
-						fulltransfer = BIU_isfulltransfer(); //Are we a full transfer?
 						++BIU[activeCPU].currentaddress; //Next address!
-						if (fulltransfer) goto fulltransferIOwrite; //Start Full transfer, when available?
+						if (unlikely((BIU[activeCPU].currentaddress&CPU_databusmask)==0)) return 1; //Handled, but broken up at this point due to the data bus not supporting transferring the rest of the word in one go!
+						goto fulltransferIOwrite; //Start Full transfer, when available?
 					}
 					return 1; //Handled!
 					break;

File UniPCemu/cpu/cpu_jmptbls.c Modified

View file
  • Ignore whitespace
  • Hide word diff
 
 */
 
-byte PIQSizes[2][NUMCPUS] = { //0=16/32-bit bus, 1=8-bit bus when available!
+byte PIQSizes[2][NUMCPUS] = { //0=16/32-bit bus, 1=Reduced(8-bit/16-bit) bus when available!
 								{6,6,6,16,32,64},
 								{4,4,6,16,32,64} //Only 8088/80188 supported in 8-bit bus!
 							}; //The PIQ buffer sizes! Pentium has two 64-byte queues. Apply settings for both 8-bit bus(8088/80188) and 16/32-bit bus (other CPUs)!
 
+byte BUSmasks[2][NUMCPUS] = { //0=16/32-bit bus, 1=Reduced bus when available!
+								{1,1,1,3,3,7},
+								{0,0,0,1,3,7} //Only 8088/80188 supported in 8-bit bus! 80386 supports 
+							}; //The BUS sizes, expressed in masks on data (d)words for memory accesses. Apply settings for both 8-bit bus(8088/80188) and 16/32-bit bus (other CPUs)!
+
 //Structure: opcode_jmptbl[whatcpu][opcode][addresssize]
 //address size=0 for 16-bits, 1 for 32-bits.