| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- using ARMeilleure.Decoders;
- using ARMeilleure.IntermediateRepresentation;
- using ARMeilleure.State;
- using ARMeilleure.Translation;
- using System;
- using System.Reflection;
- using static ARMeilleure.Instructions.InstEmitHelper;
- using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
- namespace ARMeilleure.Instructions
- {
- static partial class InstEmit32
- {
- public static void Mcr(ArmEmitterContext context)
- {
- OpCode32System op = (OpCode32System)context.CurrOp;
- if (op.Coproc != 15 || op.Opc1 != 0)
- {
- InstEmit.Und(context);
- return;
- }
- MethodInfo info;
- switch (op.CRn)
- {
- case 13: // Process and Thread Info.
- if (op.CRm != 0)
- {
- throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
- }
- switch (op.Opc2)
- {
- case 2:
- info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032)); break;
- default:
- throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
- }
- break;
- case 7:
- switch (op.CRm) // Cache and Memory barrier.
- {
- case 10:
- switch (op.Opc2)
- {
- case 5: // Data Memory Barrier Register.
- return; // No-op.
- default:
- throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16} (0x{op.RawOpCode:X}).");
- }
- default:
- throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16} (0x{op.RawOpCode:X}).");
- }
- default:
- throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
- }
- context.Call(info, GetIntA32(context, op.Rt));
- }
- public static void Mrc(ArmEmitterContext context)
- {
- OpCode32System op = (OpCode32System)context.CurrOp;
- if (op.Coproc != 15 || op.Opc1 != 0)
- {
- InstEmit.Und(context);
- return;
- }
- MethodInfo info;
- switch (op.CRn)
- {
- case 13: // Process and Thread Info.
- if (op.CRm != 0)
- {
- throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
- }
- switch (op.Opc2)
- {
- case 2:
- info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl032)); break;
- case 3:
- info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidr32)); break;
- default:
- throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
- }
- break;
- default:
- throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
- }
- if (op.Rt == RegisterAlias.Aarch32Pc)
- {
- // Special behavior: copy NZCV flags into APSR.
- EmitSetNzcv(context, context.Call(info));
- return;
- }
- else
- {
- SetIntA32(context, op.Rt, context.Call(info));
- }
- }
- public static void Mrrc(ArmEmitterContext context)
- {
- OpCode32System op = (OpCode32System)context.CurrOp;
- if (op.Coproc != 15)
- {
- InstEmit.Und(context);
- return;
- }
- int opc = op.MrrcOp;
- MethodInfo info;
- switch (op.CRm)
- {
- case 14: // Timer.
- switch (opc)
- {
- case 0:
- info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)); break;
- default:
- throw new NotImplementedException($"Unknown MRRC Opc1 0x{opc:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
- }
- break;
- default:
- throw new NotImplementedException($"Unknown MRRC 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
- }
- Operand result = context.Call(info);
- SetIntA32(context, op.Rt, context.ConvertI64ToI32(result));
- SetIntA32(context, op.CRn, context.ConvertI64ToI32(context.ShiftRightUI(result, Const(32))));
- }
- public static void Mrs(ArmEmitterContext context)
- {
- OpCode32Mrs op = (OpCode32Mrs)context.CurrOp;
- if (op.R)
- {
- throw new NotImplementedException("SPSR");
- }
- else
- {
- Operand spsr = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
- spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)));
- spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)));
- spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag)));
- spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.QFlag), Const((int)PState.QFlag)));
- // TODO: Remaining flags.
- SetIntA32(context, op.Rd, spsr);
- }
- }
- public static void Msr(ArmEmitterContext context)
- {
- OpCode32MsrReg op = (OpCode32MsrReg)context.CurrOp;
- if (op.R)
- {
- throw new NotImplementedException("SPSR");
- }
- else
- {
- if ((op.Mask & 8) != 0)
- {
- Operand value = GetIntA32(context, op.Rn);
- EmitSetNzcv(context, value);
- Operand q = context.BitwiseAnd(context.ShiftRightUI(value, Const((int)PState.QFlag)), Const(1));
- SetFlag(context, PState.QFlag, q);
- }
- if ((op.Mask & 4) != 0)
- {
- throw new NotImplementedException("APSR_g");
- }
- if ((op.Mask & 2) != 0)
- {
- throw new NotImplementedException("CPSR_x");
- }
- if ((op.Mask & 1) != 0)
- {
- throw new NotImplementedException("CPSR_c");
- }
- }
- }
- public static void Nop(ArmEmitterContext context) { }
- public static void Vmrs(ArmEmitterContext context)
- {
- OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
- if (op.Rt == RegisterAlias.Aarch32Pc && op.Sreg == 0b0001)
- {
- // Special behavior: copy NZCV flags into APSR.
- SetFlag(context, PState.VFlag, GetFpFlag(FPState.VFlag));
- SetFlag(context, PState.CFlag, GetFpFlag(FPState.CFlag));
- SetFlag(context, PState.ZFlag, GetFpFlag(FPState.ZFlag));
- SetFlag(context, PState.NFlag, GetFpFlag(FPState.NFlag));
- return;
- }
- switch (op.Sreg)
- {
- case 0b0000: // FPSID
- throw new NotImplementedException("Supervisor Only");
- case 0b0001: // FPSCR
- EmitGetFpscr(context); return;
- case 0b0101: // MVFR2
- throw new NotImplementedException("MVFR2");
- case 0b0110: // MVFR1
- throw new NotImplementedException("MVFR1");
- case 0b0111: // MVFR0
- throw new NotImplementedException("MVFR0");
- case 0b1000: // FPEXC
- throw new NotImplementedException("Supervisor Only");
- default:
- throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
- }
- }
- public static void Vmsr(ArmEmitterContext context)
- {
- OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
- switch (op.Sreg)
- {
- case 0b0000: // FPSID
- throw new NotImplementedException("Supervisor Only");
- case 0b0001: // FPSCR
- EmitSetFpscr(context); return;
- case 0b0101: // MVFR2
- throw new NotImplementedException("MVFR2");
- case 0b0110: // MVFR1
- throw new NotImplementedException("MVFR1");
- case 0b0111: // MVFR0
- throw new NotImplementedException("MVFR0");
- case 0b1000: // FPEXC
- throw new NotImplementedException("Supervisor Only");
- default:
- throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
- }
- }
- private static void EmitSetNzcv(ArmEmitterContext context, Operand t)
- {
- Operand v = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.VFlag)), Const(1));
- Operand c = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.CFlag)), Const(1));
- Operand z = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.ZFlag)), Const(1));
- Operand n = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.NFlag)), Const(1));
- SetFlag(context, PState.VFlag, v);
- SetFlag(context, PState.CFlag, c);
- SetFlag(context, PState.ZFlag, z);
- SetFlag(context, PState.NFlag, n);
- }
- private static void EmitGetFpscr(ArmEmitterContext context)
- {
- OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
- Operand fpscr = Const(0);
- for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
- {
- if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
- {
- fpscr = context.BitwiseOr(fpscr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
- }
- }
- SetIntA32(context, op.Rt, fpscr);
- }
- private static void EmitSetFpscr(ArmEmitterContext context)
- {
- OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
- Operand fpscr = GetIntA32(context, op.Rt);
- for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
- {
- if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
- {
- SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpscr, Const(flag)), Const(1)));
- }
- }
- }
- }
- }
|