From 8dca6763da435f034adb3de2f79c6ad4ef30bb00 Mon Sep 17 00:00:00 2001 From: Beyley Thomas Date: Fri, 14 Oct 2022 20:44:44 -0700 Subject: [PATCH 1/2] Implement bitwise operators --- IL2X.Core/ASMHelpers.cs | 8 +++-- IL2X.Core/Emitters/Emmiter_C.cs | 24 +++++++++++++ IL2X.Core/Jit/MethodJit.cs | 63 +++++++++++++++++++++++++++++++++ RayTraceBenchmark/Program.cs | 2 ++ 4 files changed, 95 insertions(+), 2 deletions(-) diff --git a/IL2X.Core/ASMHelpers.cs b/IL2X.Core/ASMHelpers.cs index 3332d18..5dae05c 100644 --- a/IL2X.Core/ASMHelpers.cs +++ b/IL2X.Core/ASMHelpers.cs @@ -20,7 +20,11 @@ public enum ASMCode // arithmatic Add, - Sub, + BitwiseAnd, + BitwiseOr, + BitwiseXor, + BitwiseNot, + Sub, Mul, Div, @@ -48,7 +52,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..7088236 100644 --- a/IL2X.Core/Emitters/Emmiter_C.cs +++ b/IL2X.Core/Emitters/Emmiter_C.cs @@ -488,6 +488,30 @@ 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.Sub: { var arithmaticOp = (ASMArithmatic)op; diff --git a/IL2X.Core/Jit/MethodJit.cs b/IL2X.Core/Jit/MethodJit.cs index d511f15..ef03814 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(); @@ -673,6 +718,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 +750,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..b5ae519 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; EXIT:; if (a == 124) a = -200; for (int i = 0; i != 2; ++i) From 6e37bfae8a0ac5c858927c1fe2508e4778f4b979 Mon Sep 17 00:00:00 2001 From: Beyley Thomas Date: Fri, 14 Oct 2022 21:08:46 -0700 Subject: [PATCH 2/2] Implement shl, shr, and shr.un along with respective codegen --- IL2X.Core/ASMHelpers.cs | 9 ++++++--- IL2X.Core/Emitters/Emmiter_C.cs | 20 ++++++++++++++++++++ IL2X.Core/Jit/MethodJit.cs | 33 +++++++++++++++++++++++++++++++++ RayTraceBenchmark/Program.cs | 2 +- 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/IL2X.Core/ASMHelpers.cs b/IL2X.Core/ASMHelpers.cs index 5dae05c..dd477b9 100644 --- a/IL2X.Core/ASMHelpers.cs +++ b/IL2X.Core/ASMHelpers.cs @@ -20,13 +20,16 @@ public enum ASMCode // arithmatic Add, + Sub, + Mul, + Div, BitwiseAnd, BitwiseOr, BitwiseXor, BitwiseNot, - Sub, - Mul, - Div, + ShiftLeft, + ShiftRight, + ShiftRightUnsigned, // writes WriteLocal, diff --git a/IL2X.Core/Emitters/Emmiter_C.cs b/IL2X.Core/Emitters/Emmiter_C.cs index 7088236..b4b3a43 100644 --- a/IL2X.Core/Emitters/Emmiter_C.cs +++ b/IL2X.Core/Emitters/Emmiter_C.cs @@ -512,6 +512,26 @@ private string GetOperationValue(ASMObject 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 ef03814..541365b 100644 --- a/IL2X.Core/Jit/MethodJit.cs +++ b/IL2X.Core/Jit/MethodJit.cs @@ -216,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 // =================================== diff --git a/RayTraceBenchmark/Program.cs b/RayTraceBenchmark/Program.cs index b5ae519..eccbe4d 100644 --- a/RayTraceBenchmark/Program.cs +++ b/RayTraceBenchmark/Program.cs @@ -28,7 +28,7 @@ static void Main() { int a = Foo(123); int b = 24; - int c = a ^ b & a | ~b; + int c = (a ^ b & a | ~b >> 3) << 1; EXIT:; if (a == 124) a = -200; for (int i = 0; i != 2; ++i)