ff53dcf560
* dotnet format style --severity info Some changes were manually reverted. * dotnet format analyzers --serverity info Some changes have been minimally adapted. * Restore a few unused methods and variables * Silence dotnet format IDE0060 warnings * Silence dotnet format IDE0052 warnings * Address or silence dotnet format IDE1006 warnings * Address or silence dotnet format CA2208 warnings * Address dotnet format CA1822 warnings * Address or silence dotnet format CA1069 warnings * Silence CA1806 and CA1834 issues * Address dotnet format CA1401 warnings * Fix new dotnet-format issues after rebase * Address review comments * Address dotnet format CA2208 warnings properly * Fix formatting for switch expressions * Address most dotnet format whitespace warnings * Apply dotnet format whitespace formatting A few of them have been manually reverted and the corresponding warning was silenced * Add previously silenced warnings back I have no clue how these disappeared * Revert formatting changes for OpCodeTable.cs * Enable formatting for a few cases again * Format if-blocks correctly * Enable formatting for a few more cases again * Fix inline comment alignment * Run dotnet format after rebase and remove unused usings - analyzers - style - whitespace * Disable 'prefer switch expression' rule * Add comments to disabled warnings * Remove a few unused parameters * Adjust namespaces * Simplify properties and array initialization, Use const when possible, Remove trailing commas * Start working on disabled warnings * Fix and silence a few dotnet-format warnings again * Address IDE0251 warnings * Address a few disabled IDE0060 warnings * Silence IDE0060 in .editorconfig * Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas" This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e. * dotnet format whitespace after rebase * First dotnet format pass * Remove unnecessary formatting exclusion * Add unsafe dotnet format changes * Change visibility of JitSupportDarwin to internal
278 lines
9.9 KiB
C#
278 lines
9.9 KiB
C#
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 InstEmit
|
|
{
|
|
private const int DczSizeLog2 = 4; // Log2 size in words
|
|
public const int DczSizeInBytes = 4 << DczSizeLog2;
|
|
|
|
public static void Isb(ArmEmitterContext context)
|
|
{
|
|
// Execute as no-op.
|
|
}
|
|
|
|
public static void Mrs(ArmEmitterContext context)
|
|
{
|
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
|
|
|
MethodInfo info;
|
|
|
|
switch (GetPackedId(op))
|
|
{
|
|
case 0b11_011_0000_0000_001:
|
|
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0));
|
|
break;
|
|
case 0b11_011_0000_0000_111:
|
|
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0));
|
|
break;
|
|
case 0b11_011_0100_0010_000:
|
|
EmitGetNzcv(context);
|
|
return;
|
|
case 0b11_011_0100_0100_000:
|
|
EmitGetFpcr(context);
|
|
return;
|
|
case 0b11_011_0100_0100_001:
|
|
EmitGetFpsr(context);
|
|
return;
|
|
case 0b11_011_1101_0000_010:
|
|
EmitGetTpidrEl0(context);
|
|
return;
|
|
case 0b11_011_1101_0000_011:
|
|
EmitGetTpidrroEl0(context);
|
|
return;
|
|
case 0b11_011_1110_0000_000:
|
|
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0));
|
|
break;
|
|
case 0b11_011_1110_0000_001:
|
|
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0));
|
|
break;
|
|
case 0b11_011_1110_0000_010:
|
|
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0));
|
|
break;
|
|
|
|
default:
|
|
throw new NotImplementedException($"Unknown MRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
|
}
|
|
|
|
SetIntOrZR(context, op.Rt, context.Call(info));
|
|
}
|
|
|
|
public static void Msr(ArmEmitterContext context)
|
|
{
|
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
|
|
|
switch (GetPackedId(op))
|
|
{
|
|
case 0b11_011_0100_0010_000:
|
|
EmitSetNzcv(context);
|
|
return;
|
|
case 0b11_011_0100_0100_000:
|
|
EmitSetFpcr(context);
|
|
return;
|
|
case 0b11_011_0100_0100_001:
|
|
EmitSetFpsr(context);
|
|
return;
|
|
case 0b11_011_1101_0000_010:
|
|
EmitSetTpidrEl0(context);
|
|
return;
|
|
|
|
default:
|
|
throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
|
}
|
|
}
|
|
|
|
public static void Nop(ArmEmitterContext context)
|
|
{
|
|
// Do nothing.
|
|
}
|
|
|
|
public static void Sys(ArmEmitterContext context)
|
|
{
|
|
// This instruction is used to do some operations on the CPU like cache invalidation,
|
|
// address translation and the like.
|
|
// We treat it as no-op here since we don't have any cache being emulated anyway.
|
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
|
|
|
switch (GetPackedId(op))
|
|
{
|
|
case 0b11_011_0111_0100_001:
|
|
{
|
|
// DC ZVA
|
|
Operand t = GetIntOrZR(context, op.Rt);
|
|
|
|
for (long offset = 0; offset < DczSizeInBytes; offset += 8)
|
|
{
|
|
Operand address = context.Add(t, Const(offset));
|
|
|
|
InstEmitMemoryHelper.EmitStore(context, address, RegisterConsts.ZeroIndex, 3);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
// No-op
|
|
case 0b11_011_0111_1110_001: // DC CIVAC
|
|
break;
|
|
|
|
case 0b11_011_0111_0101_001: // IC IVAU
|
|
Operand target = Register(op.Rt, RegisterType.Integer, OperandType.I64);
|
|
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)), target);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private static int GetPackedId(OpCodeSystem op)
|
|
{
|
|
int id;
|
|
|
|
id = op.Op2 << 0;
|
|
id |= op.CRm << 3;
|
|
id |= op.CRn << 7;
|
|
id |= op.Op1 << 11;
|
|
id |= op.Op0 << 14;
|
|
|
|
return id;
|
|
}
|
|
|
|
private static void EmitGetNzcv(ArmEmitterContext context)
|
|
{
|
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
|
|
|
Operand nzcv = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
|
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)));
|
|
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)));
|
|
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag)));
|
|
|
|
SetIntOrZR(context, op.Rt, nzcv);
|
|
}
|
|
|
|
private static void EmitGetFpcr(ArmEmitterContext context)
|
|
{
|
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
|
|
|
Operand fpcr = Const(0);
|
|
|
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
|
{
|
|
if (FPCR.Mask.HasFlag((FPCR)(1u << flag)))
|
|
{
|
|
fpcr = context.BitwiseOr(fpcr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
|
|
}
|
|
}
|
|
|
|
SetIntOrZR(context, op.Rt, fpcr);
|
|
}
|
|
|
|
private static void EmitGetFpsr(ArmEmitterContext context)
|
|
{
|
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
|
|
|
context.SyncQcFlag();
|
|
|
|
Operand fpsr = Const(0);
|
|
|
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
|
{
|
|
if (FPSR.Mask.HasFlag((FPSR)(1u << flag)))
|
|
{
|
|
fpsr = context.BitwiseOr(fpsr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
|
|
}
|
|
}
|
|
|
|
SetIntOrZR(context, op.Rt, fpsr);
|
|
}
|
|
|
|
private static void EmitGetTpidrEl0(ArmEmitterContext context)
|
|
{
|
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
|
|
|
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
|
|
|
Operand result = context.Load(OperandType.I64, context.Add(nativeContext, Const((ulong)NativeContext.GetTpidrEl0Offset())));
|
|
|
|
SetIntOrZR(context, op.Rt, result);
|
|
}
|
|
|
|
private static void EmitGetTpidrroEl0(ArmEmitterContext context)
|
|
{
|
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
|
|
|
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
|
|
|
Operand result = context.Load(OperandType.I64, context.Add(nativeContext, Const((ulong)NativeContext.GetTpidrroEl0Offset())));
|
|
|
|
SetIntOrZR(context, op.Rt, result);
|
|
}
|
|
|
|
private static void EmitSetNzcv(ArmEmitterContext context)
|
|
{
|
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
|
|
|
Operand nzcv = GetIntOrZR(context, op.Rt);
|
|
nzcv = context.ConvertI64ToI32(nzcv);
|
|
|
|
SetFlag(context, PState.VFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.VFlag)), Const(1)));
|
|
SetFlag(context, PState.CFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.CFlag)), Const(1)));
|
|
SetFlag(context, PState.ZFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.ZFlag)), Const(1)));
|
|
SetFlag(context, PState.NFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.NFlag)), Const(1)));
|
|
}
|
|
|
|
private static void EmitSetFpcr(ArmEmitterContext context)
|
|
{
|
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
|
|
|
Operand fpcr = GetIntOrZR(context, op.Rt);
|
|
fpcr = context.ConvertI64ToI32(fpcr);
|
|
|
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
|
{
|
|
if (FPCR.Mask.HasFlag((FPCR)(1u << flag)))
|
|
{
|
|
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpcr, Const(flag)), Const(1)));
|
|
}
|
|
}
|
|
|
|
context.UpdateArmFpMode();
|
|
}
|
|
|
|
private static void EmitSetFpsr(ArmEmitterContext context)
|
|
{
|
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
|
|
|
context.ClearQcFlagIfModified();
|
|
|
|
Operand fpsr = GetIntOrZR(context, op.Rt);
|
|
fpsr = context.ConvertI64ToI32(fpsr);
|
|
|
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
|
{
|
|
if (FPSR.Mask.HasFlag((FPSR)(1u << flag)))
|
|
{
|
|
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpsr, Const(flag)), Const(1)));
|
|
}
|
|
}
|
|
|
|
context.UpdateArmFpMode();
|
|
}
|
|
|
|
private static void EmitSetTpidrEl0(ArmEmitterContext context)
|
|
{
|
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
|
|
|
Operand value = GetIntOrZR(context, op.Rt);
|
|
|
|
Operand nativeContext = context.LoadArgument(OperandType.I64, 0);
|
|
|
|
context.Store(context.Add(nativeContext, Const((ulong)NativeContext.GetTpidrEl0Offset())), value);
|
|
}
|
|
}
|
|
}
|