| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- using ARMeilleure.Decoders;
- using ARMeilleure.IntermediateRepresentation;
- using ARMeilleure.Translation;
- using static ARMeilleure.Instructions.InstEmitHelper;
- using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
- namespace ARMeilleure.Instructions
- {
- static partial class InstEmit
- {
- public static void Bfm(ArmEmitterContext context)
- {
- OpCodeBfm op = (OpCodeBfm)context.CurrOp;
- Operand d = GetIntOrZR(context, op.Rd);
- Operand n = GetIntOrZR(context, op.Rn);
- Operand res;
- if (op.Pos < op.Shift)
- {
- // BFI.
- int shift = op.GetBitsCount() - op.Shift;
- int width = op.Pos + 1;
- long mask = (long)(ulong.MaxValue >> (64 - width));
- res = context.ShiftLeft(context.BitwiseAnd(n, Const(n.Type, mask)), Const(shift));
- res = context.BitwiseOr(res, context.BitwiseAnd(d, Const(d.Type, ~(mask << shift))));
- }
- else
- {
- // BFXIL.
- int shift = op.Shift;
- int width = op.Pos - shift + 1;
- long mask = (long)(ulong.MaxValue >> (64 - width));
- res = context.BitwiseAnd(context.ShiftRightUI(n, Const(shift)), Const(n.Type, mask));
- res = context.BitwiseOr(res, context.BitwiseAnd(d, Const(d.Type, ~mask)));
- }
- SetIntOrZR(context, op.Rd, res);
- }
- public static void Sbfm(ArmEmitterContext context)
- {
- OpCodeBfm op = (OpCodeBfm)context.CurrOp;
- int bitsCount = op.GetBitsCount();
- if (op.Pos + 1 == bitsCount)
- {
- EmitSbfmShift(context);
- }
- else if (op.Pos < op.Shift)
- {
- EmitSbfiz(context);
- }
- else if (op.Pos == 7 && op.Shift == 0)
- {
- Operand n = GetIntOrZR(context, op.Rn);
- SetIntOrZR(context, op.Rd, context.SignExtend8(n.Type, n));
- }
- else if (op.Pos == 15 && op.Shift == 0)
- {
- Operand n = GetIntOrZR(context, op.Rn);
- SetIntOrZR(context, op.Rd, context.SignExtend16(n.Type, n));
- }
- else if (op.Pos == 31 && op.Shift == 0)
- {
- Operand n = GetIntOrZR(context, op.Rn);
- SetIntOrZR(context, op.Rd, context.SignExtend32(n.Type, n));
- }
- else
- {
- Operand res = GetIntOrZR(context, op.Rn);
- res = context.ShiftLeft (res, Const(bitsCount - 1 - op.Pos));
- res = context.ShiftRightSI(res, Const(bitsCount - 1));
- res = context.BitwiseAnd (res, Const(res.Type, ~op.TMask));
- Operand n2 = GetBfmN(context);
- SetIntOrZR(context, op.Rd, context.BitwiseOr(res, n2));
- }
- }
- public static void Ubfm(ArmEmitterContext context)
- {
- OpCodeBfm op = (OpCodeBfm)context.CurrOp;
- if (op.Pos + 1 == op.GetBitsCount())
- {
- EmitUbfmShift(context);
- }
- else if (op.Pos < op.Shift)
- {
- EmitUbfiz(context);
- }
- else if (op.Pos + 1 == op.Shift)
- {
- EmitBfmLsl(context);
- }
- else if (op.Pos == 7 && op.Shift == 0)
- {
- Operand n = GetIntOrZR(context, op.Rn);
- SetIntOrZR(context, op.Rd, context.BitwiseAnd(n, Const(n.Type, 0xff)));
- }
- else if (op.Pos == 15 && op.Shift == 0)
- {
- Operand n = GetIntOrZR(context, op.Rn);
- SetIntOrZR(context, op.Rd, context.BitwiseAnd(n, Const(n.Type, 0xffff)));
- }
- else
- {
- SetIntOrZR(context, op.Rd, GetBfmN(context));
- }
- }
- private static void EmitSbfiz(ArmEmitterContext context) => EmitBfiz(context, signed: true);
- private static void EmitUbfiz(ArmEmitterContext context) => EmitBfiz(context, signed: false);
- private static void EmitBfiz(ArmEmitterContext context, bool signed)
- {
- OpCodeBfm op = (OpCodeBfm)context.CurrOp;
- int width = op.Pos + 1;
- Operand res = GetIntOrZR(context, op.Rn);
- res = context.ShiftLeft(res, Const(op.GetBitsCount() - width));
- res = signed
- ? context.ShiftRightSI(res, Const(op.Shift - width))
- : context.ShiftRightUI(res, Const(op.Shift - width));
- SetIntOrZR(context, op.Rd, res);
- }
- private static void EmitSbfmShift(ArmEmitterContext context)
- {
- EmitBfmShift(context, signed: true);
- }
- private static void EmitUbfmShift(ArmEmitterContext context)
- {
- EmitBfmShift(context, signed: false);
- }
- private static void EmitBfmShift(ArmEmitterContext context, bool signed)
- {
- OpCodeBfm op = (OpCodeBfm)context.CurrOp;
- Operand res = GetIntOrZR(context, op.Rn);
- res = signed
- ? context.ShiftRightSI(res, Const(op.Shift))
- : context.ShiftRightUI(res, Const(op.Shift));
- SetIntOrZR(context, op.Rd, res);
- }
- private static void EmitBfmLsl(ArmEmitterContext context)
- {
- OpCodeBfm op = (OpCodeBfm)context.CurrOp;
- Operand res = GetIntOrZR(context, op.Rn);
- int shift = op.GetBitsCount() - op.Shift;
- SetIntOrZR(context, op.Rd, context.ShiftLeft(res, Const(shift)));
- }
- private static Operand GetBfmN(ArmEmitterContext context)
- {
- OpCodeBfm op = (OpCodeBfm)context.CurrOp;
- Operand res = GetIntOrZR(context, op.Rn);
- long mask = op.WMask & op.TMask;
- return context.BitwiseAnd(context.RotateRight(res, Const(op.Shift)), Const(res.Type, mask));
- }
- }
- }
|