private int GetAluResult(AluRegOperation aluOp, int a, int b) { switch (aluOp) { case AluRegOperation.Add: { ulong result = (ulong)a + (ulong)b; _carry = result > 0xffffffff; return((int)result); } case AluRegOperation.AddWithCarry: { ulong result = (ulong)a + (ulong)b + (_carry ? 1UL : 0UL); _carry = result > 0xffffffff; return((int)result); } case AluRegOperation.Subtract: { ulong result = (ulong)a - (ulong)b; _carry = result < 0x100000000; return((int)result); } case AluRegOperation.SubtractWithBorrow: { ulong result = (ulong)a - (ulong)b - (_carry ? 0UL : 1UL); _carry = result < 0x100000000; return((int)result); } case AluRegOperation.BitwiseExclusiveOr: return(a ^ b); case AluRegOperation.BitwiseOr: return(a | b); case AluRegOperation.BitwiseAnd: return(a & b); case AluRegOperation.BitwiseAndNot: return(a & ~b); case AluRegOperation.BitwiseNotAnd: return(~(a & b)); } throw new ArgumentOutOfRangeException(nameof(aluOp)); }
private int GetAluResult(AluRegOperation AluOp, int A, int B) { switch (AluOp) { case AluRegOperation.Add: { ulong Result = (ulong)A + (ulong)B; Carry = Result > 0xffffffff; return((int)Result); } case AluRegOperation.AddWithCarry: { ulong Result = (ulong)A + (ulong)B + (Carry ? 1UL : 0UL); Carry = Result > 0xffffffff; return((int)Result); } case AluRegOperation.Subtract: { ulong Result = (ulong)A - (ulong)B; Carry = Result < 0x100000000; return((int)Result); } case AluRegOperation.SubtractWithBorrow: { ulong Result = (ulong)A - (ulong)B - (Carry ? 0UL : 1UL); Carry = Result < 0x100000000; return((int)Result); } case AluRegOperation.BitwiseExclusiveOr: return(A ^ B); case AluRegOperation.BitwiseOr: return(A | B); case AluRegOperation.BitwiseAnd: return(A & B); case AluRegOperation.BitwiseAndNot: return(A & ~B); case AluRegOperation.BitwiseNotAnd: return(~(A & B)); } throw new ArgumentOutOfRangeException(nameof(AluOp)); }
/// <summary> /// Gets the result of an Arithmetic and Logic operation using registers. /// </summary> /// <param name="aluOp">Arithmetic and Logic unit operation with registers</param> /// <param name="a">First operand value</param> /// <param name="b">Second operand value</param> /// <returns>Operation result</returns> private int GetAluResult(AluRegOperation aluOp, int a, int b) { ulong result; switch (aluOp) { case AluRegOperation.Add: result = (ulong)a + (ulong)b; _carry = result > 0xffffffff; return((int)result); case AluRegOperation.AddWithCarry: result = (ulong)a + (ulong)b + (_carry ? 1UL : 0UL); _carry = result > 0xffffffff; return((int)result); case AluRegOperation.Subtract: result = (ulong)a - (ulong)b; _carry = result < 0x100000000; return((int)result); case AluRegOperation.SubtractWithBorrow: result = (ulong)a - (ulong)b - (_carry ? 0UL : 1UL); _carry = result < 0x100000000; return((int)result); case AluRegOperation.BitwiseExclusiveOr: return(a ^ b); case AluRegOperation.BitwiseOr: return(a | b); case AluRegOperation.BitwiseAnd: return(a & b); case AluRegOperation.BitwiseAndNot: return(a & ~b); case AluRegOperation.BitwiseNotAnd: return(~(a & b)); } throw new InvalidOperationException($"Invalid operation \"{aluOp}\" on instruction 0x{_opCode:X8}."); }
/// <summary> /// Emits IL for a binary Arithmetic and Logic Unit instruction. /// </summary> /// <param name="aluOp">Arithmetic and Logic Unit instruction</param> /// <param name="opCode">Raw instruction</param> /// <exception cref="InvalidOperationException">Throw when the instruction encoding is invalid</exception> private void EmitAluOp(AluRegOperation aluOp, int opCode) { switch (aluOp) { case AluRegOperation.Add: EmitLoadGprA(opCode); _ilGen.Emit(OpCodes.Conv_U8); EmitLoadGprB(opCode); _ilGen.Emit(OpCodes.Conv_U8); _ilGen.Emit(OpCodes.Add); _ilGen.Emit(OpCodes.Dup); _ilGen.Emit(OpCodes.Ldc_I8, 0xffffffffL); _ilGen.Emit(OpCodes.Cgt_Un); _ilGen.Emit(OpCodes.Stloc, _carry); _ilGen.Emit(OpCodes.Conv_U4); break; case AluRegOperation.AddWithCarry: EmitLoadGprA(opCode); _ilGen.Emit(OpCodes.Conv_U8); EmitLoadGprB(opCode); _ilGen.Emit(OpCodes.Conv_U8); _ilGen.Emit(OpCodes.Ldloc_S, _carry); _ilGen.Emit(OpCodes.Conv_U8); _ilGen.Emit(OpCodes.Add); _ilGen.Emit(OpCodes.Add); _ilGen.Emit(OpCodes.Dup); _ilGen.Emit(OpCodes.Ldc_I8, 0xffffffffL); _ilGen.Emit(OpCodes.Cgt_Un); _ilGen.Emit(OpCodes.Stloc, _carry); _ilGen.Emit(OpCodes.Conv_U4); break; case AluRegOperation.Subtract: EmitLoadGprA(opCode); _ilGen.Emit(OpCodes.Conv_U8); EmitLoadGprB(opCode); _ilGen.Emit(OpCodes.Conv_U8); _ilGen.Emit(OpCodes.Sub); _ilGen.Emit(OpCodes.Dup); _ilGen.Emit(OpCodes.Ldc_I8, 0x100000000L); _ilGen.Emit(OpCodes.Clt_Un); _ilGen.Emit(OpCodes.Stloc, _carry); _ilGen.Emit(OpCodes.Conv_U4); break; case AluRegOperation.SubtractWithBorrow: EmitLoadGprA(opCode); _ilGen.Emit(OpCodes.Conv_U8); EmitLoadGprB(opCode); _ilGen.Emit(OpCodes.Conv_U8); _ilGen.Emit(OpCodes.Ldc_I4_1); _ilGen.Emit(OpCodes.Ldloc_S, _carry); _ilGen.Emit(OpCodes.Sub); _ilGen.Emit(OpCodes.Conv_U8); _ilGen.Emit(OpCodes.Sub); _ilGen.Emit(OpCodes.Sub); _ilGen.Emit(OpCodes.Dup); _ilGen.Emit(OpCodes.Ldc_I8, 0x100000000L); _ilGen.Emit(OpCodes.Clt_Un); _ilGen.Emit(OpCodes.Stloc, _carry); _ilGen.Emit(OpCodes.Conv_U4); break; case AluRegOperation.BitwiseExclusiveOr: EmitLoadGprA(opCode); EmitLoadGprB(opCode); _ilGen.Emit(OpCodes.Xor); break; case AluRegOperation.BitwiseOr: EmitLoadGprA(opCode); EmitLoadGprB(opCode); _ilGen.Emit(OpCodes.Or); break; case AluRegOperation.BitwiseAnd: EmitLoadGprA(opCode); EmitLoadGprB(opCode); _ilGen.Emit(OpCodes.And); break; case AluRegOperation.BitwiseAndNot: EmitLoadGprA(opCode); EmitLoadGprB(opCode); _ilGen.Emit(OpCodes.Not); _ilGen.Emit(OpCodes.And); break; case AluRegOperation.BitwiseNotAnd: EmitLoadGprA(opCode); EmitLoadGprB(opCode); _ilGen.Emit(OpCodes.And); _ilGen.Emit(OpCodes.Not); break; default: throw new InvalidOperationException($"Invalid operation \"{aluOp}\" 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)); }