diff --git a/IL2X.Core/ASMHelpers.cs b/IL2X.Core/ASMHelpers.cs index 3332d18..dd477b9 100644 --- a/IL2X.Core/ASMHelpers.cs +++ b/IL2X.Core/ASMHelpers.cs @@ -20,9 +20,16 @@ public enum ASMCode // arithmatic Add, - Sub, + Sub, Mul, Div, + BitwiseAnd, + BitwiseOr, + BitwiseXor, + BitwiseNot, + ShiftLeft, + ShiftRight, + ShiftRightUnsigned, // writes WriteLocal, @@ -48,7 +55,7 @@ public enum ASMCode CmpLess_1_0, // invoke - CallMethod + CallMethod, } public class ASMObject diff --git a/IL2X.Core/Emitters/Emmiter_C.cs b/IL2X.Core/Emitters/Emmiter_C.cs index f18587d..b4b3a43 100644 --- a/IL2X.Core/Emitters/Emmiter_C.cs +++ b/IL2X.Core/Emitters/Emmiter_C.cs @@ -488,6 +488,50 @@ private string GetOperationValue(ASMObject op) return $"{GetOperationValue(arithmaticOp.value1)} + {GetOperationValue(arithmaticOp.value2)}"; } + case ASMCode.BitwiseAnd: + { + var arithmaticOp = (ASMArithmatic)op; + return $"{GetOperationValue(arithmaticOp.value1)} & {GetOperationValue(arithmaticOp.value2)}"; + } + + case ASMCode.BitwiseOr: + { + var arithmaticOp = (ASMArithmatic)op; + return $"{GetOperationValue(arithmaticOp.value1)} | {GetOperationValue(arithmaticOp.value2)}"; + } + + case ASMCode.BitwiseXor: + { + var arithmaticOp = (ASMArithmatic)op; + return $"{GetOperationValue(arithmaticOp.value1)} ^ {GetOperationValue(arithmaticOp.value2)}"; + } + + case ASMCode.BitwiseNot: + { + var arithmaticOp = (ASMArithmatic)op; + return $"~{GetOperationValue(arithmaticOp.value1)}"; + } + + case ASMCode.ShiftLeft: + { + var arithmaticOp = (ASMArithmatic)op; + return $"{GetOperationValue(arithmaticOp.value1)} << {GetOperationValue(arithmaticOp.value2)}"; + } + + //NOTE: this is an arithmetic shift right + case ASMCode.ShiftRight: + { + var arithmaticOp = (ASMArithmatic)op; + return $"{GetOperationValue(arithmaticOp.value1)} >> {GetOperationValue(arithmaticOp.value2)}"; + } + + //NOTE: this is a logical shift right + case ASMCode.ShiftRightUnsigned: + { + var arithmaticOp = (ASMArithmatic)op; + return $"{GetOperationValue(arithmaticOp.value1)} >> {GetOperationValue(arithmaticOp.value2)}"; + } + case ASMCode.Sub: { var arithmaticOp = (ASMArithmatic)op; diff --git a/IL2X.Core/Jit/MethodJit.cs b/IL2X.Core/Jit/MethodJit.cs index d511f15..541365b 100644 --- a/IL2X.Core/Jit/MethodJit.cs +++ b/IL2X.Core/Jit/MethodJit.cs @@ -138,6 +138,51 @@ private void InterpretInstructionFlow(Instruction op) break; } + case Code.And: + { + var p2 = StackPop(); + var p1 = StackPop(); + var evalVarType = GetArithmaticResultType(p1.obj, p2.obj); + var evalVar = GetEvalStackVar(evalVarType); + AddASMOp(new ASMArithmatic(ASMCode.BitwiseAnd, OperandToASMOperand(p1.obj), OperandToASMOperand(p2.obj), evalVar)); + StackPush(op, evalVar); + break; + } + + case Code.Not: + { + var p1 = StackPop(); + + var evalVar = GetEvalStackVar(GetArithmaticResultType(p1.obj)); + + AddASMOp(new ASMArithmatic(ASMCode.BitwiseNot, OperandToASMOperand(p1.obj), null, evalVar)); + StackPush(op, evalVar); + break; + + } + + case Code.Or: + { + var p2 = StackPop(); + var p1 = StackPop(); + var evalVarType = GetArithmaticResultType(p1.obj, p2.obj); + var evalVar = GetEvalStackVar(evalVarType); + AddASMOp(new ASMArithmatic(ASMCode.BitwiseOr, OperandToASMOperand(p1.obj), OperandToASMOperand(p2.obj), evalVar)); + StackPush(op, evalVar); + break; + } + + case Code.Xor: + { + var p2 = StackPop(); + var p1 = StackPop(); + var evalVarType = GetArithmaticResultType(p1.obj, p2.obj); + var evalVar = GetEvalStackVar(evalVarType); + AddASMOp(new ASMArithmatic(ASMCode.BitwiseXor, OperandToASMOperand(p1.obj), OperandToASMOperand(p2.obj), evalVar)); + StackPush(op, evalVar); + break; + } + case Code.Sub: { var p2 = StackPop(); @@ -171,6 +216,39 @@ private void InterpretInstructionFlow(Instruction op) break; } + case Code.Shl: + { + var shiftAmount = StackPop(); + var value = StackPop(); + var evalVarType = GetArithmaticResultType(value.obj); + var evalVar = GetEvalStackVar(evalVarType); + AddASMOp(new ASMArithmatic(ASMCode.ShiftLeft, OperandToASMOperand(value.obj), OperandToASMOperand(shiftAmount.obj), evalVar)); + StackPush(op, evalVar); + break; + } + + case Code.Shr: + { + var shiftAmount = StackPop(); + var value = StackPop(); + var evalVarType = GetArithmaticResultType(value.obj); + var evalVar = GetEvalStackVar(evalVarType); + AddASMOp(new ASMArithmatic(ASMCode.ShiftRight, OperandToASMOperand(value.obj), OperandToASMOperand(shiftAmount.obj), evalVar)); + StackPush(op, evalVar); + break; + } + + case Code.Shr_Un: + { + var shiftAmount = StackPop(); + var value = StackPop(); + var evalVarType = GetArithmaticResultType(value.obj); + var evalVar = GetEvalStackVar(evalVarType); + AddASMOp(new ASMArithmatic(ASMCode.ShiftRightUnsigned, OperandToASMOperand(value.obj), OperandToASMOperand(shiftAmount.obj), evalVar)); + StackPush(op, evalVar); + break; + } + // =================================== // loads // =================================== @@ -673,6 +751,23 @@ private void BranchOnCondition(Instruction op, Instruction jmpToOp, ASMCode bran } } + private TypeReference GetArithmaticResultType(object value) + { + if (value is VariableReference value_Var) return value_Var.VariableType; + if (value is ParameterReference value_Param) return value_Param.ParameterType; + if (value is Int16) return GetTypeSystem().Int16; + if (value is Int32) return GetTypeSystem().Int32; + if (value is Int64) return GetTypeSystem().Int64; + if (value is UInt16) return GetTypeSystem().UInt16; + if (value is UInt32) return GetTypeSystem().UInt32; + if (value is UInt64) return GetTypeSystem().UInt64; + if (value is Single) return GetTypeSystem().Single; + if (value is Double) return GetTypeSystem().Double; + if (value is ASMSizeOf) return GetTypeSystem().Int32; + if (value is ASMEvalStackLocal local) return local.type; + throw new NotImplementedException("Unsupported arithmatic object: " + value.GetType().ToString()); + } + private TypeReference GetArithmaticResultType(object value1, object value2) { TypeReference GetType(object value) @@ -688,6 +783,7 @@ TypeReference GetType(object value) if (value is Single) return GetTypeSystem().Single; if (value is Double) return GetTypeSystem().Double; if (value is ASMSizeOf) return GetTypeSystem().Int32; + if (value is ASMEvalStackLocal local) return local.type; throw new NotImplementedException("Unsupported arithmatic object: " + value.GetType().ToString()); } diff --git a/RayTraceBenchmark/Program.cs b/RayTraceBenchmark/Program.cs index 0161d9f..eccbe4d 100644 --- a/RayTraceBenchmark/Program.cs +++ b/RayTraceBenchmark/Program.cs @@ -27,6 +27,8 @@ public class Program static void Main() { int a = Foo(123); + int b = 24; + int c = (a ^ b & a | ~b >> 3) << 1; EXIT:; if (a == 124) a = -200; for (int i = 0; i != 2; ++i)