diff options
author | LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> | 2019-12-30 02:22:47 +0100 |
---|---|---|
committer | gdkchan <gab.dark.100@gmail.com> | 2019-12-29 22:22:47 -0300 |
commit | 0915731a9dfc4e2b9263d4b30c2876446ff2d9b3 (patch) | |
tree | 46dd5369be3a2c2a3b8b6021ce164549de2b25e2 /ARMeilleure/Instructions/InstEmitAlu.cs | |
parent | ad84f3a7b3b409ceab920f480dadcfe6eda62c92 (diff) |
Implemented fast paths for: (#846)
* opt
* Nit.
* opt_p2
* Nit.
Diffstat (limited to 'ARMeilleure/Instructions/InstEmitAlu.cs')
-rw-r--r-- | ARMeilleure/Instructions/InstEmitAlu.cs | 81 |
1 files changed, 73 insertions, 8 deletions
diff --git a/ARMeilleure/Instructions/InstEmitAlu.cs b/ARMeilleure/Instructions/InstEmitAlu.cs index 947c9f70..ed1faae4 100644 --- a/ARMeilleure/Instructions/InstEmitAlu.cs +++ b/ARMeilleure/Instructions/InstEmitAlu.cs @@ -2,6 +2,7 @@ using ARMeilleure.Decoders; using ARMeilleure.IntermediateRepresentation; using ARMeilleure.State; using ARMeilleure.Translation; +using System.Diagnostics; using static ARMeilleure.Instructions.InstEmitAluHelper; using static ARMeilleure.Instructions.InstEmitHelper; @@ -265,16 +266,52 @@ namespace ARMeilleure.Instructions if (op.RegisterSize == RegisterSize.Int32) { - d = context.Call(new _U32_U32(SoftFallback.ReverseBits32), n); + d = EmitReverseBits32Op(context, n); } else { - d = context.Call(new _U64_U64(SoftFallback.ReverseBits64), n); + d = EmitReverseBits64Op(context, n); } SetAluDOrZR(context, d); } + private static Operand EmitReverseBits32Op(ArmEmitterContext context, Operand op) + { + Debug.Assert(op.Type == OperandType.I32); + + Operand val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xaaaaaaaau)), Const(1)), + context.ShiftLeft (context.BitwiseAnd(op, Const(0x55555555u)), Const(1))); + + val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xccccccccu)), Const(2)), + context.ShiftLeft (context.BitwiseAnd(val, Const(0x33333333u)), Const(2))); + val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xf0f0f0f0u)), Const(4)), + context.ShiftLeft (context.BitwiseAnd(val, Const(0x0f0f0f0fu)), Const(4))); + val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xff00ff00u)), Const(8)), + context.ShiftLeft (context.BitwiseAnd(val, Const(0x00ff00ffu)), Const(8))); + + return context.BitwiseOr(context.ShiftRightUI(val, Const(16)), context.ShiftLeft(val, Const(16))); + } + + private static Operand EmitReverseBits64Op(ArmEmitterContext context, Operand op) + { + Debug.Assert(op.Type == OperandType.I64); + + Operand val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xaaaaaaaaaaaaaaaaul)), Const(1)), + context.ShiftLeft (context.BitwiseAnd(op, Const(0x5555555555555555ul)), Const(1))); + + val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xccccccccccccccccul)), Const(2)), + context.ShiftLeft (context.BitwiseAnd(val, Const(0x3333333333333333ul)), Const(2))); + val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xf0f0f0f0f0f0f0f0ul)), Const(4)), + context.ShiftLeft (context.BitwiseAnd(val, Const(0x0f0f0f0f0f0f0f0ful)), Const(4))); + val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xff00ff00ff00ff00ul)), Const(8)), + context.ShiftLeft (context.BitwiseAnd(val, Const(0x00ff00ff00ff00fful)), Const(8))); + val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xffff0000ffff0000ul)), Const(16)), + context.ShiftLeft (context.BitwiseAnd(val, Const(0x0000ffff0000fffful)), Const(16))); + + return context.BitwiseOr(context.ShiftRightUI(val, Const(32)), context.ShiftLeft(val, Const(32))); + } + public static void Rev16(ArmEmitterContext context) { OpCodeAlu op = (OpCodeAlu)context.CurrOp; @@ -284,32 +321,60 @@ namespace ARMeilleure.Instructions if (op.RegisterSize == RegisterSize.Int32) { - d = context.Call(new _U32_U32(SoftFallback.ReverseBytes16_32), n); + d = EmitReverseBytes16_32Op(context, n); } else { - d = context.Call(new _U64_U64(SoftFallback.ReverseBytes16_64), n); + d = EmitReverseBytes16_64Op(context, n); } SetAluDOrZR(context, d); } + private static Operand EmitReverseBytes16_32Op(ArmEmitterContext context, Operand op) + { + Debug.Assert(op.Type == OperandType.I32); + + Operand val = EmitReverseBytes16_64Op(context, context.ZeroExtend32(OperandType.I64, op)); + + return context.ConvertI64ToI32(val); + } + + private static Operand EmitReverseBytes16_64Op(ArmEmitterContext context, Operand op) + { + Debug.Assert(op.Type == OperandType.I64); + + return context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xff00ff00ff00ff00ul)), Const(8)), + context.ShiftLeft (context.BitwiseAnd(op, Const(0x00ff00ff00ff00fful)), Const(8))); + } + public static void Rev32(ArmEmitterContext context) { OpCodeAlu op = (OpCodeAlu)context.CurrOp; Operand n = GetIntOrZR(context, op.Rn); + Operand d; if (op.RegisterSize == RegisterSize.Int32) { - SetAluDOrZR(context, context.ByteSwap(n)); + d = context.ByteSwap(n); } else { - Operand d = context.Call(new _U64_U64(SoftFallback.ReverseBytes32_64), n); - - SetAluDOrZR(context, d); + d = EmitReverseBytes32_64Op(context, n); } + + SetAluDOrZR(context, d); + } + + private static Operand EmitReverseBytes32_64Op(ArmEmitterContext context, Operand op) + { + Debug.Assert(op.Type == OperandType.I64); + + Operand val = EmitReverseBytes16_64Op(context, op); + + return context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xffff0000ffff0000ul)), Const(16)), + context.ShiftLeft (context.BitwiseAnd(val, Const(0x0000ffff0000fffful)), Const(16))); } public static void Rev64(ArmEmitterContext context) |