/// <summary> /// Gets the result of the current Arithmetic and Logic unit operation. /// </summary> /// <param name="state">Current GPU state</param> /// <returns>Operation result</returns> private int GetAluResult(GpuState state) { AluOperation op = (AluOperation)(_opCode & 7); switch (op) { case AluOperation.AluReg: return(GetAluResult((AluRegOperation)((_opCode >> 17) & 0x1f), GetGprA(), GetGprB())); case AluOperation.AddImmediate: return(GetGprA() + GetImm()); case AluOperation.BitfieldReplace: case AluOperation.BitfieldExtractLslImm: case AluOperation.BitfieldExtractLslReg: int bfSrcBit = (_opCode >> 17) & 0x1f; int bfSize = (_opCode >> 22) & 0x1f; int bfDstBit = (_opCode >> 27) & 0x1f; int bfMask = (1 << bfSize) - 1; int dst = GetGprA(); int src = GetGprB(); switch (op) { case AluOperation.BitfieldReplace: src = (int)((uint)src >> bfSrcBit) & bfMask; dst &= ~(bfMask << bfDstBit); dst |= src << bfDstBit; return(dst); case AluOperation.BitfieldExtractLslImm: src = (int)((uint)src >> dst) & bfMask; return(src << bfDstBit); case AluOperation.BitfieldExtractLslReg: src = (int)((uint)src >> bfSrcBit) & bfMask; return(src << dst); } break; case AluOperation.ReadImmediate: return(Read(state, GetGprA() + GetImm())); } throw new InvalidOperationException($"Invalid operation \"{op}\" on instruction 0x{_opCode:X8}."); }
/// <summary> /// Emits IL for a Arithmetic and Logic Unit instruction. /// </summary> /// <param name="opCode">Instruction to be translated</param> /// <exception cref="InvalidOperationException">Throw when the instruction encoding is invalid</exception> private void EmitAluOp(int opCode) { AluOperation op = (AluOperation)(opCode & 7); switch (op) { case AluOperation.AluReg: EmitAluOp((AluRegOperation)((opCode >> 17) & 0x1f), opCode); break; case AluOperation.AddImmediate: EmitLoadGprA(opCode); EmitLoadImm(opCode); _ilGen.Emit(OpCodes.Add); break; case AluOperation.BitfieldReplace: case AluOperation.BitfieldExtractLslImm: case AluOperation.BitfieldExtractLslReg: int bfSrcBit = (opCode >> 17) & 0x1f; int bfSize = (opCode >> 22) & 0x1f; int bfDstBit = (opCode >> 27) & 0x1f; int bfMask = (1 << bfSize) - 1; switch (op) { case AluOperation.BitfieldReplace: EmitLoadGprB(opCode); _ilGen.Emit(OpCodes.Ldc_I4, bfSrcBit); _ilGen.Emit(OpCodes.Shr_Un); _ilGen.Emit(OpCodes.Ldc_I4, bfMask); _ilGen.Emit(OpCodes.And); _ilGen.Emit(OpCodes.Ldc_I4, bfDstBit); _ilGen.Emit(OpCodes.Shl); EmitLoadGprA(opCode); _ilGen.Emit(OpCodes.Ldc_I4, ~(bfMask << bfDstBit)); _ilGen.Emit(OpCodes.And); _ilGen.Emit(OpCodes.Or); break; case AluOperation.BitfieldExtractLslImm: EmitLoadGprB(opCode); EmitLoadGprA(opCode); _ilGen.Emit(OpCodes.Shr_Un); _ilGen.Emit(OpCodes.Ldc_I4, bfMask); _ilGen.Emit(OpCodes.And); _ilGen.Emit(OpCodes.Ldc_I4, bfDstBit); _ilGen.Emit(OpCodes.Shl); break; case AluOperation.BitfieldExtractLslReg: EmitLoadGprB(opCode); _ilGen.Emit(OpCodes.Ldc_I4, bfSrcBit); _ilGen.Emit(OpCodes.Shr_Un); _ilGen.Emit(OpCodes.Ldc_I4, bfMask); _ilGen.Emit(OpCodes.And); EmitLoadGprA(opCode); _ilGen.Emit(OpCodes.Shl); break; } break; case AluOperation.ReadImmediate: _ilGen.Emit(OpCodes.Ldarg_1); EmitLoadGprA(opCode); EmitLoadImm(opCode); _ilGen.Emit(OpCodes.Add); _ilGen.Emit(OpCodes.Call, typeof(MacroJitContext).GetMethod(nameof(MacroJitContext.Read))); break; default: throw new InvalidOperationException($"Invalid operation \"{op}\" on instruction 0x{opCode:X8}."); } }
private int GetAluResult() { AluOperation op = (AluOperation)(_opCode & 7); switch (op) { case AluOperation.AluReg: { AluRegOperation aluOp = (AluRegOperation)((_opCode >> 17) & 0x1f); return(GetAluResult(aluOp, GetGprA(), GetGprB())); } case AluOperation.AddImmediate: { return(GetGprA() + GetImm()); } case AluOperation.BitfieldReplace: case AluOperation.BitfieldExtractLslImm: case AluOperation.BitfieldExtractLslReg: { int bfSrcBit = (_opCode >> 17) & 0x1f; int bfSize = (_opCode >> 22) & 0x1f; int bfDstBit = (_opCode >> 27) & 0x1f; int bfMask = (1 << bfSize) - 1; int dst = GetGprA(); int src = GetGprB(); switch (op) { case AluOperation.BitfieldReplace: { src = (int)((uint)src >> bfSrcBit) & bfMask; dst &= ~(bfMask << bfDstBit); dst |= src << bfDstBit; return(dst); } case AluOperation.BitfieldExtractLslImm: { src = (int)((uint)src >> dst) & bfMask; return(src << bfDstBit); } case AluOperation.BitfieldExtractLslReg: { src = (int)((uint)src >> bfSrcBit) & bfMask; return(src << dst); } } break; } case AluOperation.ReadImmediate: { return(Read(GetGprA() + GetImm())); } } throw new ArgumentException(nameof(_opCode)); }
private int GetAluResult() { AluOperation Op = (AluOperation)(OpCode & 7); switch (Op) { case AluOperation.AluReg: { AluRegOperation AluOp = (AluRegOperation)((OpCode >> 17) & 0x1f); return(GetAluResult(AluOp, GetGprA(), GetGprB())); } case AluOperation.AddImmediate: { return(GetGprA() + GetImm()); } case AluOperation.BitfieldReplace: case AluOperation.BitfieldExtractLslImm: case AluOperation.BitfieldExtractLslReg: { int BfSrcBit = (OpCode >> 17) & 0x1f; int BfSize = (OpCode >> 22) & 0x1f; int BfDstBit = (OpCode >> 27) & 0x1f; int BfMask = (1 << BfSize) - 1; int Dst = GetGprA(); int Src = GetGprB(); switch (Op) { case AluOperation.BitfieldReplace: { Src = (int)((uint)Src >> BfSrcBit) & BfMask; Dst &= ~(BfMask << BfDstBit); Dst |= Src << BfDstBit; return(Dst); } case AluOperation.BitfieldExtractLslImm: { Src = (int)((uint)Src >> Dst) & BfMask; return(Src << BfDstBit); } case AluOperation.BitfieldExtractLslReg: { Src = (int)((uint)Src >> BfSrcBit) & BfMask; return(Src << Dst); } } break; } case AluOperation.ReadImmediate: { return(Read(GetGprA() + GetImm())); } } throw new ArgumentException(nameof(OpCode)); }