aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2019-02-26 06:16:50 -0300
committerjduncanator <1518948+jduncanator@users.noreply.github.com>2019-02-26 20:16:50 +1100
commitef3f9a2abe85cfd572ab6bec73481e3526762dcc (patch)
treeb11a6b2ac91848021c45eafd45d4e02b0de74c0d
parent504f4f4abfd34696699fbf484264404f3011ec17 (diff)
Optmize BFM instruction (#607)
-rw-r--r--ChocolArm64/Instructions/InstEmitBfm.cs55
1 files changed, 45 insertions, 10 deletions
diff --git a/ChocolArm64/Instructions/InstEmitBfm.cs b/ChocolArm64/Instructions/InstEmitBfm.cs
index d25af8be..4a039599 100644
--- a/ChocolArm64/Instructions/InstEmitBfm.cs
+++ b/ChocolArm64/Instructions/InstEmitBfm.cs
@@ -11,21 +11,56 @@ namespace ChocolArm64.Instructions
{
OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp;
- EmitBfmLoadRn(context);
+ if (op.Pos < op.Shift)
+ {
+ //BFI.
+ context.EmitLdintzr(op.Rn);
- context.EmitLdintzr(op.Rd);
- context.EmitLdc_I(~op.WMask & op.TMask);
+ int shift = op.GetBitsCount() - op.Shift;
- context.Emit(OpCodes.And);
- context.Emit(OpCodes.Or);
+ int width = op.Pos + 1;
- context.EmitLdintzr(op.Rd);
- context.EmitLdc_I(~op.TMask);
+ long mask = (long)(ulong.MaxValue >> (64 - width));
- context.Emit(OpCodes.And);
- context.Emit(OpCodes.Or);
+ context.EmitLdc_I(mask);
- context.EmitStintzr(op.Rd);
+ context.Emit(OpCodes.And);
+
+ context.EmitLsl(shift);
+
+ context.EmitLdintzr(op.Rd);
+
+ context.EmitLdc_I(~(mask << shift));
+
+ context.Emit(OpCodes.And);
+ context.Emit(OpCodes.Or);
+
+ context.EmitStintzr(op.Rd);
+ }
+ else
+ {
+ //BFXIL.
+ context.EmitLdintzr(op.Rn);
+
+ context.EmitLsr(op.Shift);
+
+ int width = op.Pos - op.Shift + 1;
+
+ long mask = (long)(ulong.MaxValue >> (64 - width));
+
+ context.EmitLdc_I(mask);
+
+ context.Emit(OpCodes.And);
+
+ context.EmitLdintzr(op.Rd);
+
+ context.EmitLdc_I(~mask);
+
+ context.Emit(OpCodes.And);
+ context.Emit(OpCodes.Or);
+
+ context.EmitStintzr(op.Rd);
+ }
}
public static void Sbfm(ILEmitterCtx context)