mirror of
				https://github.com/Ryujinx/Ryujinx.git
				synced 2025-10-25 10:32:26 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			208 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using ChocolArm64.Decoder;
 | |
| using ChocolArm64.State;
 | |
| using ChocolArm64.Translation;
 | |
| using System.Reflection.Emit;
 | |
| 
 | |
| namespace ChocolArm64.Instruction
 | |
| {
 | |
|     static partial class AInstEmit
 | |
|     {
 | |
|         public static void Bfm(AILEmitterCtx Context)
 | |
|         {
 | |
|             AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
 | |
| 
 | |
|             EmitBfmLoadRn(Context);
 | |
| 
 | |
|             Context.EmitLdintzr(Op.Rd);
 | |
|             Context.EmitLdc_I(~Op.WMask & Op.TMask);
 | |
| 
 | |
|             Context.Emit(OpCodes.And);
 | |
|             Context.Emit(OpCodes.Or);
 | |
| 
 | |
|             Context.EmitLdintzr(Op.Rd);
 | |
|             Context.EmitLdc_I(~Op.TMask);
 | |
| 
 | |
|             Context.Emit(OpCodes.And);
 | |
|             Context.Emit(OpCodes.Or);
 | |
| 
 | |
|             Context.EmitStintzr(Op.Rd);
 | |
|         }
 | |
| 
 | |
|         public static void Sbfm(AILEmitterCtx Context)
 | |
|         {
 | |
|             AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
 | |
| 
 | |
|             int BitsCount = Op.GetBitsCount();
 | |
| 
 | |
|             if (Op.Pos + 1 == BitsCount)
 | |
|             {
 | |
|                 EmitSbfmShift(Context);
 | |
|             }
 | |
|             else if (Op.Pos < Op.Shift)
 | |
|             {
 | |
|                 EmitSbfiz(Context);
 | |
|             }
 | |
|             else if (Op.Pos == 7 && Op.Shift == 0)
 | |
|             {
 | |
|                 EmitSbfmCast(Context, OpCodes.Conv_I1);
 | |
|             }
 | |
|             else if (Op.Pos == 15 && Op.Shift == 0)
 | |
|             {
 | |
|                 EmitSbfmCast(Context, OpCodes.Conv_I2);
 | |
|             }
 | |
|             else if (Op.Pos == 31 && Op.Shift == 0)
 | |
|             {
 | |
|                 EmitSbfmCast(Context, OpCodes.Conv_I4);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 EmitBfmLoadRn(Context);
 | |
| 
 | |
|                 Context.EmitLdintzr(Op.Rn);
 | |
| 
 | |
|                 Context.EmitLsl(BitsCount - 1 - Op.Pos);
 | |
|                 Context.EmitAsr(BitsCount - 1);
 | |
| 
 | |
|                 Context.EmitLdc_I(~Op.TMask);
 | |
| 
 | |
|                 Context.Emit(OpCodes.And);
 | |
|                 Context.Emit(OpCodes.Or);
 | |
| 
 | |
|                 Context.EmitStintzr(Op.Rd);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public static void Ubfm(AILEmitterCtx Context)
 | |
|         {
 | |
|             AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
 | |
| 
 | |
|             if (Op.Pos + 1 == Op.GetBitsCount())
 | |
|             {
 | |
|                 EmitUbfmShift(Context);
 | |
|             }
 | |
|             else if (Op.Pos < Op.Shift)
 | |
|             {
 | |
|                 EmitUbfiz(Context);
 | |
|             }
 | |
|             else if (Op.Pos + 1 == Op.Shift)
 | |
|             {
 | |
|                 EmitBfmLsl(Context);
 | |
|             }
 | |
|             else if (Op.Pos == 7 && Op.Shift == 0)
 | |
|             {
 | |
|                 EmitUbfmCast(Context, OpCodes.Conv_U1);
 | |
|             }
 | |
|             else if (Op.Pos == 15 && Op.Shift == 0)
 | |
|             {
 | |
|                 EmitUbfmCast(Context, OpCodes.Conv_U2);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 EmitBfmLoadRn(Context);
 | |
| 
 | |
|                 Context.EmitStintzr(Op.Rd);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private static void EmitSbfiz(AILEmitterCtx Context) => EmitBfiz(Context, true);
 | |
|         private static void EmitUbfiz(AILEmitterCtx Context) => EmitBfiz(Context, false);
 | |
| 
 | |
|         private static void EmitBfiz(AILEmitterCtx Context, bool Signed)
 | |
|         {
 | |
|             AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
 | |
| 
 | |
|             int Width = Op.Pos + 1;
 | |
| 
 | |
|             Context.EmitLdintzr(Op.Rn);
 | |
| 
 | |
|             Context.EmitLsl(Op.GetBitsCount() - Width);
 | |
| 
 | |
|             if (Signed)
 | |
|             {
 | |
|                 Context.EmitAsr(Op.Shift - Width);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 Context.EmitLsr(Op.Shift - Width);
 | |
|             }
 | |
| 
 | |
|             Context.EmitStintzr(Op.Rd);
 | |
|         }
 | |
| 
 | |
|         private static void EmitSbfmCast(AILEmitterCtx Context, OpCode ILOp)
 | |
|         {
 | |
|             EmitBfmCast(Context, ILOp, true);
 | |
|         }
 | |
| 
 | |
|         private static void EmitUbfmCast(AILEmitterCtx Context, OpCode ILOp)
 | |
|         {
 | |
|             EmitBfmCast(Context, ILOp, false);
 | |
|         }
 | |
| 
 | |
|         private static void EmitBfmCast(AILEmitterCtx Context, OpCode ILOp, bool Signed)
 | |
|         {
 | |
|             AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
 | |
| 
 | |
|             Context.EmitLdintzr(Op.Rn);
 | |
| 
 | |
|             Context.Emit(ILOp);
 | |
| 
 | |
|             if (Op.RegisterSize != ARegisterSize.Int32)
 | |
|             {
 | |
|                 Context.Emit(Signed
 | |
|                     ? OpCodes.Conv_I8
 | |
|                     : OpCodes.Conv_U8);
 | |
|             }
 | |
| 
 | |
|             Context.EmitStintzr(Op.Rd);
 | |
|         }
 | |
| 
 | |
|         private static void EmitSbfmShift(AILEmitterCtx Context)
 | |
|         {
 | |
|             EmitBfmShift(Context, true);
 | |
|         }
 | |
| 
 | |
|         private static void EmitUbfmShift(AILEmitterCtx Context)
 | |
|         {
 | |
|             EmitBfmShift(Context, false);
 | |
|         }
 | |
| 
 | |
|         private static void EmitBfmShift(AILEmitterCtx Context, bool Signed)
 | |
|         {
 | |
|             AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
 | |
| 
 | |
|             Context.EmitLdintzr(Op.Rn);
 | |
|             Context.EmitLdc_I4(Op.Shift);
 | |
| 
 | |
|             Context.Emit(Signed
 | |
|                 ? OpCodes.Shr
 | |
|                 : OpCodes.Shr_Un);
 | |
| 
 | |
|             Context.EmitStintzr(Op.Rd);
 | |
|         }
 | |
| 
 | |
|         private static void EmitBfmLsl(AILEmitterCtx Context)
 | |
|         {
 | |
|             AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
 | |
| 
 | |
|             Context.EmitLdintzr(Op.Rn);
 | |
| 
 | |
|             Context.EmitLsl(Op.GetBitsCount() - Op.Shift);
 | |
| 
 | |
|             Context.EmitStintzr(Op.Rd);
 | |
|         }
 | |
| 
 | |
|         private static void EmitBfmLoadRn(AILEmitterCtx Context)
 | |
|         {
 | |
|             AOpCodeBfm Op = (AOpCodeBfm)Context.CurrOp;
 | |
| 
 | |
|             Context.EmitLdintzr(Op.Rn);
 | |
| 
 | |
|             Context.EmitRor(Op.Shift);
 | |
| 
 | |
|             Context.EmitLdc_I(Op.WMask & Op.TMask);
 | |
| 
 | |
|             Context.Emit(OpCodes.And);
 | |
|         }
 | |
|     }
 | |
| } |