From 9cb57fb4bb3bbae0ae052a5af4a96a49fc5d864d Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Tue, 30 Oct 2018 19:43:02 -0600 Subject: Adjust naming conventions for Ryujinx and ChocolArm64 projects (#484) * Change naming convention for Ryujinx project * Change naming convention for ChocolArm64 project * Fix NaN * Remove unneeded this. from Ryujinx project * Adjust naming from new PRs * Name changes based on feedback * How did this get removed? * Rebasing fix * Change FP enum case * Remove prefix from ChocolArm64 classes - Part 1 * Remove prefix from ChocolArm64 classes - Part 2 * Fix alignment from last commit's renaming * Rename namespaces * Rename stragglers * Fix alignment * Rename OpCode class * Missed a few * Adjust alignment --- ChocolArm64/Instructions/InstEmitMemoryEx.cs | 192 +++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 ChocolArm64/Instructions/InstEmitMemoryEx.cs (limited to 'ChocolArm64/Instructions/InstEmitMemoryEx.cs') diff --git a/ChocolArm64/Instructions/InstEmitMemoryEx.cs b/ChocolArm64/Instructions/InstEmitMemoryEx.cs new file mode 100644 index 00000000..42daca63 --- /dev/null +++ b/ChocolArm64/Instructions/InstEmitMemoryEx.cs @@ -0,0 +1,192 @@ +using ChocolArm64.Decoders; +using ChocolArm64.Memory; +using ChocolArm64.State; +using ChocolArm64.Translation; +using System; +using System.Reflection.Emit; +using System.Threading; + +using static ChocolArm64.Instructions.InstEmitMemoryHelper; + +namespace ChocolArm64.Instructions +{ + static partial class InstEmit + { + [Flags] + private enum AccessType + { + None = 0, + Ordered = 1, + Exclusive = 2, + OrderedEx = Ordered | Exclusive + } + + public static void Clrex(ILEmitterCtx context) + { + EmitMemoryCall(context, nameof(MemoryManager.ClearExclusive)); + } + + public static void Dmb(ILEmitterCtx context) => EmitBarrier(context); + public static void Dsb(ILEmitterCtx context) => EmitBarrier(context); + + public static void Ldar(ILEmitterCtx context) => EmitLdr(context, AccessType.Ordered); + public static void Ldaxr(ILEmitterCtx context) => EmitLdr(context, AccessType.OrderedEx); + public static void Ldxr(ILEmitterCtx context) => EmitLdr(context, AccessType.Exclusive); + public static void Ldxp(ILEmitterCtx context) => EmitLdp(context, AccessType.Exclusive); + public static void Ldaxp(ILEmitterCtx context) => EmitLdp(context, AccessType.OrderedEx); + + private static void EmitLdr(ILEmitterCtx context, AccessType accType) + { + EmitLoad(context, accType, false); + } + + private static void EmitLdp(ILEmitterCtx context, AccessType accType) + { + EmitLoad(context, accType, true); + } + + private static void EmitLoad(ILEmitterCtx context, AccessType accType, bool pair) + { + OpCodeMemEx64 op = (OpCodeMemEx64)context.CurrOp; + + bool ordered = (accType & AccessType.Ordered) != 0; + bool exclusive = (accType & AccessType.Exclusive) != 0; + + if (ordered) + { + EmitBarrier(context); + } + + if (exclusive) + { + EmitMemoryCall(context, nameof(MemoryManager.SetExclusive), op.Rn); + } + + context.EmitLdint(op.Rn); + context.EmitSttmp(); + + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + context.EmitLdtmp(); + + EmitReadZxCall(context, op.Size); + + context.EmitStintzr(op.Rt); + + if (pair) + { + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + context.EmitLdtmp(); + context.EmitLdc_I8(1 << op.Size); + + context.Emit(OpCodes.Add); + + EmitReadZxCall(context, op.Size); + + context.EmitStintzr(op.Rt2); + } + } + + public static void Pfrm(ILEmitterCtx context) + { + //Memory Prefetch, execute as no-op. + } + + public static void Stlr(ILEmitterCtx context) => EmitStr(context, AccessType.Ordered); + public static void Stlxr(ILEmitterCtx context) => EmitStr(context, AccessType.OrderedEx); + public static void Stxr(ILEmitterCtx context) => EmitStr(context, AccessType.Exclusive); + public static void Stxp(ILEmitterCtx context) => EmitStp(context, AccessType.Exclusive); + public static void Stlxp(ILEmitterCtx context) => EmitStp(context, AccessType.OrderedEx); + + private static void EmitStr(ILEmitterCtx context, AccessType accType) + { + EmitStore(context, accType, false); + } + + private static void EmitStp(ILEmitterCtx context, AccessType accType) + { + EmitStore(context, accType, true); + } + + private static void EmitStore(ILEmitterCtx context, AccessType accType, bool pair) + { + OpCodeMemEx64 op = (OpCodeMemEx64)context.CurrOp; + + bool ordered = (accType & AccessType.Ordered) != 0; + bool exclusive = (accType & AccessType.Exclusive) != 0; + + if (ordered) + { + EmitBarrier(context); + } + + ILLabel lblEx = new ILLabel(); + ILLabel lblEnd = new ILLabel(); + + if (exclusive) + { + EmitMemoryCall(context, nameof(MemoryManager.TestExclusive), op.Rn); + + context.Emit(OpCodes.Brtrue_S, lblEx); + + context.EmitLdc_I8(1); + context.EmitStintzr(op.Rs); + + context.Emit(OpCodes.Br_S, lblEnd); + } + + context.MarkLabel(lblEx); + + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + context.EmitLdint(op.Rn); + context.EmitLdintzr(op.Rt); + + EmitWriteCall(context, op.Size); + + if (pair) + { + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + context.EmitLdint(op.Rn); + context.EmitLdc_I8(1 << op.Size); + + context.Emit(OpCodes.Add); + + context.EmitLdintzr(op.Rt2); + + EmitWriteCall(context, op.Size); + } + + if (exclusive) + { + context.EmitLdc_I8(0); + context.EmitStintzr(op.Rs); + + EmitMemoryCall(context, nameof(MemoryManager.ClearExclusiveForStore)); + } + + context.MarkLabel(lblEnd); + } + + private static void EmitMemoryCall(ILEmitterCtx context, string name, int rn = -1) + { + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + context.EmitLdarg(TranslatedSub.StateArgIdx); + + context.EmitCallPropGet(typeof(CpuThreadState), nameof(CpuThreadState.Core)); + + if (rn != -1) + { + context.EmitLdint(rn); + } + + context.EmitCall(typeof(MemoryManager), name); + } + + private static void EmitBarrier(ILEmitterCtx context) + { + //Note: This barrier is most likely not necessary, and probably + //doesn't make any difference since we need to do a ton of stuff + //(software MMU emulation) to read or write anything anyway. + context.EmitCall(typeof(Thread), nameof(Thread.MemoryBarrier)); + } + } +} \ No newline at end of file -- cgit v1.2.3