Example #1
0
        public static void EmitLoadRegister( GenerationContext context, byte reg, byte fmt )
        {
            if( ( fmt == 0 ) || ( fmt == 4 ) )
            {
                context.ILGen.Emit( OpCodes.Ldarg_0 );
                context.ILGen.Emit( OpCodes.Ldfld, context.Core0Cp1 );
                context.ILGen.Emit( OpCodes.Ldfld, context.Cp1Registers );
                context.ILGen.Emit( OpCodes.Ldc_I4, ( int )reg );
                context.ILGen.Emit( OpCodes.Ldelem_R4 );

                //if( fmt == 4 )
                //	context.ILGen.Emit( OpCodes.Conv_I4 );
            }
            else
            {
                Debug.Assert( false );
            }
        }
Example #2
0
 public static void EmitStoreRegister( GenerationContext context, byte reg, byte fmt )
 {
     if( ( fmt == 0 ) || ( fmt == 4 ) )
     {
         if( fmt == 4 )
         {
             context.ILGen.Emit( OpCodes.Conv_I4 );
             context.ILGen.Emit( OpCodes.Conv_R4 );
         }
         context.ILGen.Emit( OpCodes.Stloc_S, ( byte )Cpu.LocalTempD1 );
         context.ILGen.Emit( OpCodes.Ldarg_0 );
         context.ILGen.Emit( OpCodes.Ldfld, context.Core0Cp1 );
         context.ILGen.Emit( OpCodes.Ldfld, context.Cp1Registers );
         context.ILGen.Emit( OpCodes.Ldc_I4, ( int )reg );
         context.ILGen.Emit( OpCodes.Ldloc_S, ( byte )Cpu.LocalTempD1 );
         context.ILGen.Emit( OpCodes.Stelem_R4 );
     }
     else
     {
         Debug.Assert( false );
     }
 }
Example #3
0
 public static void EmitConvertFormat( GenerationContext context, byte originalFmt, byte targetFmt )
 {
     if( originalFmt == targetFmt )
         return;
     else if( targetFmt == 0 )
     {
         context.ILGen.Emit( OpCodes.Conv_R4 );
     }
     else if( targetFmt == 1 )
     {
         Debug.Assert( false );
     }
     else if( targetFmt == 4 )
     {
         context.ILGen.Emit( OpCodes.Conv_I4 );
         context.ILGen.Emit( OpCodes.Conv_R4 );
     }
     else if( targetFmt == 5 )
     {
         Debug.Assert( false );
     }
 }
Example #4
0
			public static GenerationResult DIVU( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, byte rd, byte shamt, byte function )
			{
				if( pass == 0 )
				{
					context.ReadRegisters[ rs ] = true;
					context.ReadRegisters[ rt ] = true;
					context.UseCore = true;
				}
				else if( pass == 1 )
				{
					EmitLoadRegister( context, rs );
					context.ILGen.Emit( OpCodes.Stloc_0 );
					EmitLoadRegister( context, rt );
					context.ILGen.Emit( OpCodes.Stloc_1 );

					context.ILGen.Emit( OpCodes.Ldarg_0 );
					context.ILGen.Emit( OpCodes.Ldloc_0 );
					context.ILGen.Emit( OpCodes.Conv_U4 );
					context.ILGen.Emit( OpCodes.Ldloc_1 );
					context.ILGen.Emit( OpCodes.Conv_U4 );
					context.ILGen.Emit( OpCodes.Div_Un );
					context.ILGen.Emit( OpCodes.Stfld, context.Core0Lo );

					context.ILGen.Emit( OpCodes.Ldarg_0 );
					context.ILGen.Emit( OpCodes.Ldloc_0 );
					context.ILGen.Emit( OpCodes.Conv_U4 );
					context.ILGen.Emit( OpCodes.Ldloc_1 );
					context.ILGen.Emit( OpCodes.Conv_U4 );
					context.ILGen.Emit( OpCodes.Rem_Un );
					context.ILGen.Emit( OpCodes.Stfld, context.Core0Hi );

					//long rem;
					//context.Lo.Value = Math.DivRem( rs, rt, out rem );
					//context.Hi.Value = rem;
				}
				return GenerationResult.Success;
			}
Example #5
0
			public static GenerationResult MTLO( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, byte rd, byte shamt, byte function )
			{
				if( pass == 0 )
				{
					context.ReadRegisters[ rs ] = true;
					context.UseCore = true;
				}
				else if( pass == 1 )
				{
					context.ILGen.Emit( OpCodes.Ldarg_0 );
					EmitLoadRegister( context, rs );
					context.ILGen.Emit( OpCodes.Stfld, context.Core0Lo );
					//context.Lo.Value = rs;
				}
				return GenerationResult.Success;
			}
Example #6
0
		public static void EmitSingleToWord( GenerationContext context )
		{
#if FASTSINGLEWORDCONVERT
			context.ILGen.Emit( OpCodes.Conv_R4 );
			context.ILGen.Emit( OpCodes.Stloc_S, ( byte )Cpu.LocalTempF );
			context.ILGen.Emit( OpCodes.Ldloca_S, ( byte )Cpu.LocalTempF );
			context.ILGen.Emit( OpCodes.Conv_U );
			context.ILGen.Emit( OpCodes.Ldind_I4 );
#else
			context.ILGen.Emit( OpCodes.Conv_R4 );
			context.ILGen.Emit( OpCodes.Call, typeof( BitConverter ).GetMethod( "GetBytes", new Type[] { typeof( float ) } ) );
			context.ILGen.Emit( OpCodes.Ldc_I4_0 );
			context.ILGen.Emit( OpCodes.Call, typeof( BitConverter ).GetMethod( "ToInt32" ) );
#endif
		}
Example #7
0
		public static void DefineBranchTarget( GenerationContext context, int target )
		{
			if( context.BranchLabels.ContainsKey( target ) == false )
			{
				//Debug.WriteLine( string.Format( "Defining branch target {0:X8}", target ) );
				LabelMarker lm = new LabelMarker( target );
				context.BranchLabels.Add( target, lm );
			}
			if( context.LastBranchTarget < target )
				context.LastBranchTarget = target;
		}
Example #8
0
		public static void EmitDirectMemoryWrite( GenerationContext context )
		{
			// If the address is within main memory bounds, we do a direct read on it
			// If it's not, pass to the normal one
			// Stack: Memory / Address / Value

			Label l1 = context.ILGen.DefineLabel();
			Label l2 = context.ILGen.DefineLabel();
			Label l3 = context.ILGen.DefineLabel();

			context.ILGen.Emit( OpCodes.Stloc_1 );

			//if( ( address >= 0x08000000 ) && ( address < 0x09FFFFFF ) )
			context.ILGen.Emit( OpCodes.Dup );
			context.ILGen.Emit( OpCodes.Dup );
			context.ILGen.Emit( OpCodes.Ldc_I4, 0x08000000 );
			context.ILGen.Emit( OpCodes.Blt, l1 );
			context.ILGen.Emit( OpCodes.Ldc_I4, 0x09FFFFFF );
			context.ILGen.Emit( OpCodes.Bgt, l2 );

			// Address is within main memory range
			// Stack: Memory / Translated address
			context.ILGen.Emit( OpCodes.Ldc_I4, 0x08000000 );
			context.ILGen.Emit( OpCodes.Sub );
			context.ILGen.Emit( OpCodes.Stloc_0 );

			context.ILGen.Emit( OpCodes.Ldfld, context.MemoryMainBuffer );
			context.ILGen.Emit( OpCodes.Ldloc_0 );
			context.ILGen.Emit( OpCodes.Ldelema, typeof( byte ) );
			context.ILGen.Emit( OpCodes.Ldloc_1 );
			context.ILGen.Emit( OpCodes.Stind_I4 );
			context.ILGen.Emit( OpCodes.Br_S, l3 );

			context.ILGen.MarkLabel( l1 );
			context.ILGen.Emit( OpCodes.Pop );
			context.ILGen.MarkLabel( l2 );

			// Address is not within main memory range
			// Stack: Memory / Translated address

			context.ILGen.Emit( OpCodes.Ldc_I4_4 );
			context.ILGen.Emit( OpCodes.Ldloc_1 );
			context.ILGen.Emit( OpCodes.Callvirt, context.MemoryWriteWord );

			context.ILGen.MarkLabel( l3 );
		}
Example #9
0
		public static void EmitAddressTranslation( GenerationContext context )
		{
			// This is here to check for crazy kernel addresses or other things
			// - technically we shouldn't have to do this (on a real PSP they
			// would cause crashes), but the pspdev stuff sometimes does weird
			// things - except for uncached reads/writes, etc

			//if( ( address & 0x80000000 ) != 0 )
			//    address = address & 0x7FFFFFFF;
			//if( ( address & 0x40000000 ) != 0 )
			//    address = address & 0x3FFFFFFF;

			context.ILGen.Emit( OpCodes.Ldc_I4, 0x3FFFFFFF );
			context.ILGen.Emit( OpCodes.And );
		}
Example #10
0
			public static GenerationResult BREAK( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, byte rd, byte shamt, byte function )
			{
				if( pass == 0 )
				{
				}
				else if( pass == 1 )
				{
					context.ILGen.Emit( OpCodes.Call, typeof( Debugger ).GetMethod( "Break" ) );
				}
				return GenerationResult.Success;
			}
Example #11
0
			public static GenerationResult SYSCALL( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, byte rd, byte shamt, byte function )
			{
				// We could probably save a register write by properly obeying the
				// hasReturn flag, but I'm not confident the functions all have that
				// filled properly and I'd hate to introduce bugs like that
				// FUTURE: Ensure BIOS methods all have proper HasReturn and enable selective return storage

				int syscall = ( int )( ( code >> 6 ) & 0xFFFFF );

				BiosFunction biosFunction = context.Cpu._syscalls[ syscall ];
				bool willCall;
				bool hasReturn;
				int paramCount;
				if( biosFunction != null )
				{
					willCall = biosFunction.IsImplemented;
					hasReturn = biosFunction.HasReturn;
					paramCount = biosFunction.ParameterCount;

					if( biosFunction.IsImplemented == false )
					{
						if( pass == 0 )
						{
							Debug.WriteLine( string.Format( "DynRec: NID 0x{0:X8} {1} is not implemented",
								biosFunction.NID, biosFunction.Name ) );
						}
					}
				}
				else
				{
					willCall = false;
					hasReturn = false;
					paramCount = 0;

					if( pass == 0 )
						Debug.WriteLine( "DynRec: unregistered syscall attempt" );
				}

				if( pass == 0 )
				{
					context.UseMemory = true;
					context.UseSyscalls = true;

					if( willCall == true )
					{
						if( paramCount > 0 )
						{
							context.ReadRegisters[ 4 ] = true;
							if( paramCount > 1 )
							{
								context.ReadRegisters[ 5 ] = true;
								if( paramCount > 2 )
								{
									context.ReadRegisters[ 6 ] = true;
									if( paramCount > 3 )
									{
										context.ReadRegisters[ 7 ] = true;
										if( paramCount > 4 )
										{
											// Maybe this should always go?
											context.ReadRegisters[ 29 ] = true;
										}
									}
								}
							}
						}
						if( hasReturn == true )
						{
							context.WriteRegisters[ 2 ] = true;
						}
					}
				}
				else if( pass == 1 )
				{
					// It's important that we save what we think is the current PC
					// If we had an UpdatePc, it means a branch has updated it before us
					// and we need to save it - otherwise, save the PC following us
					context.ILGen.Emit( OpCodes.Ldarg_0 );
					if( context.UpdatePc == true )
						context.ILGen.Emit( OpCodes.Ldloc_2 );
					else
						context.ILGen.Emit( OpCodes.Ldc_I4, address + 4 );
					context.ILGen.Emit( OpCodes.Stfld, context.Core0Pc );

#if VERBOSESYSCALLS
					context.ILGen.Emit( OpCodes.Ldarg_3 );
					context.ILGen.Emit( OpCodes.Ldc_I4, syscall );
					context.ILGen.Emit( OpCodes.Ldelem, typeof( BiosFunction ) );
					context.ILGen.Emit( OpCodes.Call, typeof( Special ).GetMethod( "SyscallDebugThunk" ) );
#endif

					if( willCall == true )
					{
						// Lame, but we need the object this gets called on and
						// there is no way to communicate what we know now to the final IL
						//context.Cpu._syscalls[ syscall ].Target.Target;
						context.ILGen.Emit( OpCodes.Ldarg_3 );
						context.ILGen.Emit( OpCodes.Ldc_I4, syscall );
						context.ILGen.Emit( OpCodes.Ldelem, typeof( BiosFunction ) );
						context.ILGen.Emit( OpCodes.Ldfld, context.BiosFunctionTarget );
						context.ILGen.Emit( OpCodes.Call, context.DelegateTargetGet );
						
						// Memory
						context.ILGen.Emit( OpCodes.Ldarg_1 );

						if( paramCount > 0 )
						{
							EmitLoadRegister( context, 4 );
							if( paramCount > 1 )
							{
								EmitLoadRegister( context, 5 );
								if( paramCount > 2 )
								{
									EmitLoadRegister( context, 6 );
									if( paramCount > 3 )
									{
										EmitLoadRegister( context, 7 );
										if( paramCount > 4 )
										{
											// Maybe this should always go?
											EmitLoadRegister( context, 29 );
										}
										else
											context.ILGen.Emit( OpCodes.Ldc_I4_0 );
									}
									else
									{
										context.ILGen.Emit( OpCodes.Ldc_I4_0 );
										context.ILGen.Emit( OpCodes.Ldc_I4_0 );
									}
								}
								else
								{
									context.ILGen.Emit( OpCodes.Ldc_I4_0 );
									context.ILGen.Emit( OpCodes.Ldc_I4_0 );
									context.ILGen.Emit( OpCodes.Ldc_I4_0 );
								}
							}
							else
							{
								context.ILGen.Emit( OpCodes.Ldc_I4_0 );
								context.ILGen.Emit( OpCodes.Ldc_I4_0 );
								context.ILGen.Emit( OpCodes.Ldc_I4_0 );
								context.ILGen.Emit( OpCodes.Ldc_I4_0 );
							}
						}
						else
						{
							context.ILGen.Emit( OpCodes.Ldc_I4_0 );
							context.ILGen.Emit( OpCodes.Ldc_I4_0 );
							context.ILGen.Emit( OpCodes.Ldc_I4_0 );
							context.ILGen.Emit( OpCodes.Ldc_I4_0 );
							context.ILGen.Emit( OpCodes.Ldc_I4_0 );
						}

						if( biosFunction.Target.Method.IsFinal == true )
							context.ILGen.Emit( OpCodes.Call, biosFunction.Target.Method );
						else
							context.ILGen.Emit( OpCodes.Callvirt, biosFunction.Target.Method );

						// Function returns a value - may need to ignore
						if( hasReturn == true )
							EmitStoreRegister( context, 2 );
						else
							context.ILGen.Emit( OpCodes.Pop );
					}
					else
					{
						// When we fail, we need to make sure to handle the cases where
						// the method has a return or else things could get even worse!
						if( biosFunction != null )
						{
							if( hasReturn == true )
							{
								context.ILGen.Emit( OpCodes.Ldc_I4, -1 );
								EmitStoreRegister( context, 2 );
							}
						}
					}
				}
				return GenerationResult.Syscall;
			}
Example #12
0
			public static GenerationResult NOP( GenerationContext context, int pass, int address, uint code, byte rs, byte rt, byte rd )
			{
				EmitNop( context );
				return GenerationResult.Success;
			}
Example #13
0
			public static GenerationResult BGEZALL( GenerationContext context, int pass, int address, uint code, byte opcode, uint imm )
			{
				int target = ( address + AddressOffset ) + ( ( int )( short )imm << 2 );

				int rs = ( int )( ( code >> 21 ) & 0x1F );
				if( pass == 0 )
				{
					context.UpdatePc = true;
					context.ReadRegisters[ rs ] = true;
					context.WriteRegisters[ 31 ] = true;
					DefineBranchTarget( context, target );
				}
				else if( pass == 1 )
				{
					LabelMarker targetLabel = context.BranchLabels[ target ];
					//Debug.Assert( targetLabel != default( Label ) );
					context.BranchTarget = targetLabel;

					Label l1 = context.ILGen.DefineLabel();
					Label l2 = context.ILGen.DefineLabel();
					EmitLoadRegister( context, rs );
					//context.ILGen.Emit( OpCodes.Ldc_I4_0 );
					//context.ILGen.Emit( OpCodes.Blt, l1 );
					context.ILGen.Emit( OpCodes.Ldc_I4, 31 );
					context.ILGen.Emit( OpCodes.Shr );
					context.ILGen.Emit( OpCodes.Ldc_I4_0 );
					context.ILGen.Emit( OpCodes.Bne_Un, l1 );
					context.ILGen.Emit( OpCodes.Ldc_I4, address + 4 );
					EmitStoreRegister( context, 31 );
					context.ILGen.Emit( OpCodes.Ldc_I4_1 );
					context.ILGen.Emit( OpCodes.Stloc_3 );
					context.ILGen.Emit( OpCodes.Br_S, l2 );
					context.ILGen.MarkLabel( l1 );
					context.ILGen.Emit( OpCodes.Ldc_I4_1 );
					context.ILGen.Emit( OpCodes.Stloc_S, ( byte )Cpu.LocalNullifyDelay );
					context.ILGen.MarkLabel( l2 );
				}
				//if( rs.Value >= 0 )
				//{
				//	context.Registers[ 31 ].Value = context.PC + 4;
				//	context.PC.Value = context.PC + ( imm << 2 );
				//}
				//else
				//	null = true;
				return GenerationResult.BranchAndNullifyDelay;
			}
Example #14
0
		public static void EmitStoreRegister( GenerationContext context, int reg )
		{
			Debug.Assert( ( reg >= 0 ) && ( reg <= 31 ) );

			if( reg != 0 )
			{
				//int map = context.Registers[ reg ];
				//context.ILGen.Emit( OpCodes.Stloc_S, ( byte )map );
				context.ILGen.Emit( OpCodes.Stloc_1 );
				context.ILGen.Emit( OpCodes.Ldarg_2 );
				context.ILGen.Emit( OpCodes.Ldc_I4, reg );
				context.ILGen.Emit( OpCodes.Ldloc_1 );
				context.ILGen.Emit( OpCodes.Stelem_I4 );
			}
			else
				context.ILGen.Emit( OpCodes.Pop );
		}
Example #15
0
			public static GenerationResult BLTZ( GenerationContext context, int pass, int address, uint code, byte opcode, uint imm )
			{
				int target = ( address + AddressOffset ) + ( ( int )( short )imm << 2 );

				int rs = ( int )( ( code >> 21 ) & 0x1F );
				if( pass == 0 )
				{
					context.UpdatePc = true;
					context.ReadRegisters[ rs ] = true;
					DefineBranchTarget( context, target );
				}
				else if( pass == 1 )
				{
					LabelMarker targetLabel = context.BranchLabels[ target ];
					//Debug.Assert( targetLabel != default( Label ) );
					context.BranchTarget = targetLabel;

					Label l1 = context.ILGen.DefineLabel();
					EmitLoadRegister( context, rs );
					//context.ILGen.Emit( OpCodes.Ldc_I4_0 );
					//context.ILGen.Emit( OpCodes.Bge, l1 );
					context.ILGen.Emit( OpCodes.Ldc_I4, 31 );
					context.ILGen.Emit( OpCodes.Shr );
					context.ILGen.Emit( OpCodes.Ldc_I4_1 );
					context.ILGen.Emit( OpCodes.Bne_Un, l1 );
					context.ILGen.Emit( OpCodes.Ldc_I4_1 );
					context.ILGen.Emit( OpCodes.Stloc_3 );
					context.ILGen.MarkLabel( l1 );
				}
				//if( rs.Value < 0 )
				//	context.PC.Value = context.PC + ( imm << 2 );
				return GenerationResult.Branch;
			}
Example #16
0
			public static GenerationResult CTCz( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, ushort imm )
			{
				return GenerationResult.Invalid;

				//if( pass == 0 )
				//{
				//    context.ReadRegisters[ rs ] = true;
				//    context.WriteRegisters[ rt ] = true;
				//}
				//else if( pass == 1 )
				//{
				//    EmitLoadRegister( context, rs );
				//    context.ILGen.Emit( OpCodes.Ldc_I4, ( int )( uint )imm );
				//    context.ILGen.Emit( OpCodes.And );
				//    EmitStoreRegister( context, rt );
				//    //rt.Value = rs & imm;
				//}
				//return GenerationResult.Success;
			}
Example #17
0
		public static void EmitStoreCopConditionBit( GenerationContext context, int cop )
		{
			Debug.Assert( cop == 1 );
			context.ILGen.Emit( OpCodes.Stloc_0 );
			context.ILGen.Emit( OpCodes.Ldarg_0 );
			context.ILGen.Emit( OpCodes.Ldfld, context.Core0Cp1 );
			context.ILGen.Emit( OpCodes.Ldloc_0 );
			context.ILGen.Emit( OpCodes.Conv_U1 );
			context.ILGen.Emit( OpCodes.Call, context.Cp1ConditionBitSet );
		}
Example #18
0
			public static GenerationResult COP2( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, ushort imm )
			{
				if( pass == 0 )
				{
				}
				else if( pass == 1 )
				{
				}
				return GenerationResult.Invalid;
			}
Example #19
0
		public static void EmitDirectMemoryRead( GenerationContext context )
		{
			// If the address is within main memory bounds, we do a direct read on it
			// If it's not, pass to the nromal one
			// Stack: Memory / Address

			Label l1 = context.ILGen.DefineLabel();
			Label l2 = context.ILGen.DefineLabel();
			Label l3 = context.ILGen.DefineLabel();

			//if( ( address >= 0x08000000 ) && ( address < 0x09FFFFFF ) )
			context.ILGen.Emit( OpCodes.Dup );
			context.ILGen.Emit( OpCodes.Dup );
			context.ILGen.Emit( OpCodes.Ldc_I4, 0x08000000 );
			context.ILGen.Emit( OpCodes.Blt, l1 );
			context.ILGen.Emit( OpCodes.Ldc_I4, 0x09FFFFFF );
			context.ILGen.Emit( OpCodes.Bgt, l2 );

			// Address is within main memory range
			// Stack: Memory / Translated address
			context.ILGen.Emit( OpCodes.Ldc_I4, 0x08000000 );
			context.ILGen.Emit( OpCodes.Sub );
			context.ILGen.Emit( OpCodes.Stloc_0 );

			//context.ILGen.Emit( OpCodes.Ldstr, "read inline 0x{0:X8}" );
			//context.ILGen.Emit( OpCodes.Ldloc_0 );
			//context.ILGen.Emit( OpCodes.Ldc_I4, 0x08000000 );
			//context.ILGen.Emit( OpCodes.Add );
			//context.ILGen.Emit( OpCodes.Box, typeof( int ) );
			//context.ILGen.Emit( OpCodes.Call, context.StringFormat1 );
			//context.ILGen.Emit( OpCodes.Call, context.DebugWriteLine );

			context.ILGen.Emit( OpCodes.Ldfld, context.MemoryMainBuffer );
			context.ILGen.Emit( OpCodes.Ldloc_0 );
			context.ILGen.Emit( OpCodes.Ldelema, typeof( byte ) );
			context.ILGen.Emit( OpCodes.Ldind_I4 );
			context.ILGen.Emit( OpCodes.Br_S, l3 );

			context.ILGen.MarkLabel( l1 );
			context.ILGen.Emit( OpCodes.Pop );
			context.ILGen.MarkLabel( l2 );

			// Address is not within main memory range
			// Stack: Memory / Translated address

			context.ILGen.Emit( OpCodes.Callvirt, context.MemoryReadWord );

			context.ILGen.MarkLabel( l3 );
		}
Example #20
0
			// TODO: Allegrex mtic
			public static GenerationResult MTIC( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, byte rd, byte shamt, byte function )
			{
				if( pass == 0 )
				{
				}
				else if( pass == 1 )
				{
				}
				return GenerationResult.Success;
			}
Example #21
0
		public static void EmitNop( GenerationContext context )
		{
		}
Example #22
0
			public static GenerationResult HandleInstruction( GenerationContext context, int pass, int address, uint code )
			{
				uint copop = code >> 28;
				byte cop = ( byte )( ( code >> 26 ) & 0x3 ); // cop0, cop1, or cop2
				byte rs = ( byte )( ( code >> 21 ) & 0x1F );
				byte rt = ( byte )( ( code >> 16 ) & 0x1F );
				byte rd = ( byte )( ( code >> 11 ) & 0x1F );
				ushort imm = ( ushort )( code & 0xFFFF );

				// rs = bc sub-opcode
				// rt = branch condition

				switch( copop )
				{
					case 0x4:
						if( ( ( code >> 25 ) & 0x1 ) == 1 )	// COPz
						{
							uint cofun = code & 0x1FFFFFF;

							if( cop == 1 )
							{
								byte fmt = ( byte )( ( cofun >> 21 ) & 0x1F );
								// 0 = S = single binary fp
								// 1 = D = double binary fp
								// 4 = W = single 32 binary fixed point
								// 5 = L = longword 64 binary fixed point
								Debug.Assert( ( fmt != 1 ) && ( fmt != 5 ) );
								byte ft = rt; // source 2
								byte fs = rd; // source 1
								byte fd = ( byte )( ( code >> 6 ) & 0x1F ); // dest
								byte func = ( byte )( code & 0x3F );

								GenerateInstructionFpu instr = FpuInstructions.TableFpu[ func ];
								if( pass == 1 )
									context.Cpu.EmitTrace( context, address, code, instr.Method.Name, string.Format( "fmt:{0} fs:{1} ft:{2} fd:{3}", fmt, fs, ft, fd ) );
								return instr( context, pass, address + 4, code, fmt, fs, ft, fd, func );
							}
							else
							{
								Debug.WriteLine( string.Format( "Cpu: attempted COP{0} function {1:X8}", cop, cofun ) );
								return GenerationResult.Invalid;
							}
						}
						else
						{
							switch( rs )
							{
								case 0x00:			// mfcz rt, rd
									if( pass == 1 )
										context.Cpu.EmitTrace( context, address, code, "MFCz", string.Format( "cop:{3} rd:{0} rt:{1} imm:{2}", cop, rd, rt, ( int )( short )imm ) );
									return Cop.MFCz( context, pass, address, code, cop, rd, rt, imm );
								case 0x04:			// mtcz rt, rd
									if( pass == 1 )
										context.Cpu.EmitTrace( context, address, code, "MTCz", string.Format( "cop:{3} rd:{0} rt:{1} imm:{2}", cop, rd, rt, ( int )( short )imm ) );
									return Cop.MTCz( context, pass, address, code, cop, rd, rt, imm );
								case 0x02:			// cfcz rt, rd
									if( pass == 1 )
										context.Cpu.EmitTrace( context, address, code, "CFCz", string.Format( "cop:{3} rd:{0} rt:{1} imm:{2}", cop, rd, rt, ( int )( short )imm ) );
									return Cop.CFCz( context, pass, address, code, cop, rd, rt, imm );
								case 0x06:			// ctcz rt, rd
									if( pass == 1 )
										context.Cpu.EmitTrace( context, address, code, "CTCz", string.Format( "cop:{3} rd:{0} rt:{1} imm:{2}", cop, rd, rt, ( int )( short )imm ) );
									return Cop.CTCz( context, pass, address, code, cop, rd, rt, imm );
								case 0x08:
									{
										switch( rt )
										{
											case 0x0:		// BCzF
												if( pass == 1 )
													context.Cpu.EmitTrace( context, address, code, "BCzF", string.Format( "cop:{3} rs:{0} rt:{1} imm:{2}", cop, rs, rt, ( int )( short )imm ) );
												return Cop.BCzF( context, pass, address, code, cop, rs, rt, imm );
											case 0x2:		// BCzFL
												if( pass == 1 )
													context.Cpu.EmitTrace( context, address, code, "BCzFL", string.Format( "cop:{3} rs:{0} rt:{1} imm:{2}", cop, rs, rt, ( int )( short )imm ) );
												return Cop.BCzFL( context, pass, address, code, cop, rs, rt, imm );
											case 0x1:		// BCzT
												if( pass == 1 )
													context.Cpu.EmitTrace( context, address, code, "BCzT", string.Format( "cop:{3} rs:{0} rt:{1} imm:{2}", cop, rs, rt, ( int )( short )imm ) );
												return Cop.BCzT( context, pass, address, code, cop, rs, rt, imm );
											case 0x3:		// BCzTL
												if( pass == 1 )
													context.Cpu.EmitTrace( context, address, code, "BCzTL", string.Format( "cop:{3} rs:{0} rt:{1} imm:{2}", cop, rs, rt, ( int )( short )imm ) );
												return Cop.BCzTL( context, pass, address, code, cop, rs, rt, imm );
										}

										if( cop == 1 )
										{
											// Hand off to COP1 to do it's thing
											//_cp1->Process( instruction );
											Debug.Assert( false );
											return GenerationResult.Invalid;
										}
									}
									return GenerationResult.Invalid;
							}
						}
						return GenerationResult.Invalid;
				}

				return GenerationResult.Invalid;
			}
Example #23
0
		public static void EmitWordToSingle( GenerationContext context )
		{
#if FASTSINGLEWORDCONVERT
			context.ILGen.Emit( OpCodes.Stloc_0 );
			context.ILGen.Emit( OpCodes.Ldloca_S, 0 );
			context.ILGen.Emit( OpCodes.Conv_U );
			context.ILGen.Emit( OpCodes.Ldind_R4 );
#else
			context.ILGen.Emit( OpCodes.Conv_I4 );
			context.ILGen.Emit( OpCodes.Call, typeof( BitConverter ).GetMethod( "GetBytes", new Type[] { typeof( int ) } ) );
			context.ILGen.Emit( OpCodes.Ldc_I4_0 );
			context.ILGen.Emit( OpCodes.Call, typeof( BitConverter ).GetMethod( "ToSingle" ) );
#endif
		}
Example #24
0
		public static void EmitStoreCopRegister( GenerationContext context, int cop, int reg )
		{
			Debug.Assert( ( reg >= 0 ) && ( reg <= 31 ) );

			switch( cop )
			{
				case 0:
					{
						// Cop1 stuff not done
						Debug.Assert( false );
					}
					break;
				case 1:
					{
						context.ILGen.Emit( OpCodes.Conv_R4 );
						context.ILGen.Emit( OpCodes.Stloc_S, ( byte )Cpu.LocalTempD1 );

						context.ILGen.Emit( OpCodes.Ldarg_0 );
						context.ILGen.Emit( OpCodes.Ldfld, context.Core0Cp1 );
						context.ILGen.Emit( OpCodes.Ldfld, context.Cp1Registers );

						context.ILGen.Emit( OpCodes.Ldc_I4, ( int )reg );
						context.ILGen.Emit( OpCodes.Ldloc_S, ( byte )Cpu.LocalTempD1 );
						context.ILGen.Emit( OpCodes.Stelem_R4 );
					}
					break;
				case 2:
					{
						// Cop2 not implemented
						Debug.Assert( false );
					}
					break;
			}
		}
Example #25
0
			public static GenerationResult MFLO( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, byte rd, byte shamt, byte function )
			{
				if( pass == 0 )
				{
					context.WriteRegisters[ rd ] = true;
					context.UseCore = true;
				}
				else if( pass == 1 )
				{
					context.ILGen.Emit( OpCodes.Ldarg_0 );
					context.ILGen.Emit( OpCodes.Ldfld, context.Core0Lo );
					EmitStoreRegister( context, rd );
					//rd.Value = context.Lo;
				}
				return GenerationResult.Success;
			}
Example #26
0
			public static GenerationResult BCzTL( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, ushort imm )
			{
				int target = ( address + AddressOffset ) + ( ( int )( short )imm << 2 );

				//targetPcValid = condition;
				//nullifyDelay = !targetPcValid;
				if( pass == 0 )
				{
					context.UpdatePc = true;
					DefineBranchTarget( context, target );
				}
				else if( pass == 1 )
				{
					LabelMarker targetLabel = context.BranchLabels[ target ];
					//Debug.Assert( targetLabel != default( Label ) );
					context.BranchTarget = targetLabel;

					Label l1 = context.ILGen.DefineLabel();
					Label l2 = context.ILGen.DefineLabel();
					EmitLoadCopConditionBit( context, opcode );
					context.ILGen.Emit( OpCodes.Brfalse_S, l1 );
					context.ILGen.Emit( OpCodes.Ldc_I4_1 );
					context.ILGen.Emit( OpCodes.Stloc_3 );
					context.ILGen.Emit( OpCodes.Br_S, l2 );
					context.ILGen.MarkLabel( l1 );
					context.ILGen.Emit( OpCodes.Ldc_I4_1 );
					context.ILGen.Emit( OpCodes.Stloc_S, ( byte )Cpu.LocalNullifyDelay );
					context.ILGen.MarkLabel( l2 );
				}
				return GenerationResult.BranchAndNullifyDelay;
			}
Example #27
0
			public static GenerationResult MULTU( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, byte rd, byte shamt, byte function )
			{
				if( pass == 0 )
				{
					context.ReadRegisters[ rs ] = true;
					context.ReadRegisters[ rt ] = true;
					context.UseCore = true;
				}
				else if( pass == 1 )
				{
					context.ILGen.Emit( OpCodes.Ldarg_0 );

					EmitLoadRegister( context, rs );
					context.ILGen.Emit( OpCodes.Conv_U8 );
					EmitLoadRegister( context, rt );
					context.ILGen.Emit( OpCodes.Conv_U8 );
					context.ILGen.Emit( OpCodes.Mul_Ovf_Un );

					context.ILGen.Emit( OpCodes.Dup );
					context.ILGen.Emit( OpCodes.Conv_I4 );
					context.ILGen.Emit( OpCodes.Stloc_0 );

					context.ILGen.Emit( OpCodes.Ldc_I4, 32 );
					context.ILGen.Emit( OpCodes.Shr_Un );
					context.ILGen.Emit( OpCodes.Conv_I4 );
					context.ILGen.Emit( OpCodes.Stfld, context.Core0Hi );

					context.ILGen.Emit( OpCodes.Ldarg_0 );
					context.ILGen.Emit( OpCodes.Ldloc_0 );
					context.ILGen.Emit( OpCodes.Stfld, context.Core0Lo );

					//long res = rs * rt;
					//context.Hi.Value = ( int )( res >> 32 );
					//context.Lo.Value = ( int )res;
				}
				return GenerationResult.Success;
			}
Example #28
0
			public static GenerationResult MFCz( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, ushort imm )
			{
				if( pass == 0 )
				{
					context.WriteRegisters[ rt ] = true;
				}
				else if( pass == 1 )
				{
					EmitLoadCopRegister( context, opcode, rs );

					if( opcode == 1 )
						EmitSingleToWord( context );

					EmitStoreRegister( context, rt );
				}
				return GenerationResult.Success;
			}
Example #29
0
			public static GenerationResult OR( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, byte rd, byte shamt, byte function )
			{
				if( pass == 0 )
				{
					context.ReadRegisters[ rs ] = true;
					context.ReadRegisters[ rt ] = true;
					context.WriteRegisters[ rd ] = true;
				}
				else if( pass == 1 )
				{
					EmitLoadRegister( context, rs );
					EmitLoadRegister( context, rt );
					context.ILGen.Emit( OpCodes.Or );
					EmitStoreRegister( context, rd );
					//rd.Value = rs | rt;
				}
				return GenerationResult.Success;
			}
Example #30
0
			public static GenerationResult MTCz( GenerationContext context, int pass, int address, uint code, byte opcode, byte rs, byte rt, ushort imm )
			{
				if( pass == 0 )
				{
					context.ReadRegisters[ rs ] = true;
				}
				else if( pass == 1 )
				{
					EmitLoadRegister( context, rt );

					if( opcode == 1 )
						EmitWordToSingle( context );

					//context.ILGen.Emit( OpCodes.Stloc_S, ( byte )Cpu.LocalTempD1 );

					//context.ILGen.Emit( OpCodes.Ldstr, string.Format( "{0:X8}: mtcz {{0}}", address - 4 ) );
					//context.ILGen.Emit( OpCodes.Ldloc_S, ( byte )Cpu.LocalTempD1 );
					//context.ILGen.Emit( OpCodes.Box, typeof( float ) );
					//context.ILGen.Emit( OpCodes.Call, context.StringFormat1 );
					//context.ILGen.Emit( OpCodes.Call, context.DebugWriteLine );

					//context.ILGen.Emit( OpCodes.Ldloc_S, ( byte )Cpu.LocalTempD1 );
					
					EmitStoreCopRegister( context, opcode, rs );
				}
				return GenerationResult.Success;
			}