Split main project into core,graphics and chocolarm4 subproject (#29)
This commit is contained in:
parent
cb665bb715
commit
62b827f474
257 changed files with 415 additions and 285 deletions
180
ChocolArm64/Instruction/AInstEmitMemoryEx.cs
Normal file
180
ChocolArm64/Instruction/AInstEmitMemoryEx.cs
Normal file
|
@ -0,0 +1,180 @@
|
|||
using ChocolArm64.Decoder;
|
||||
using ChocolArm64.Memory;
|
||||
using ChocolArm64.Translation;
|
||||
using System;
|
||||
using System.Reflection.Emit;
|
||||
using System.Threading;
|
||||
|
||||
using static ChocolArm64.Instruction.AInstEmitMemoryHelper;
|
||||
|
||||
namespace ChocolArm64.Instruction
|
||||
{
|
||||
static partial class AInstEmit
|
||||
{
|
||||
[Flags]
|
||||
private enum AccessType
|
||||
{
|
||||
None = 0,
|
||||
Ordered = 1,
|
||||
Exclusive = 2,
|
||||
OrderedEx = Ordered | Exclusive
|
||||
}
|
||||
|
||||
public static void Clrex(AILEmitterCtx Context)
|
||||
{
|
||||
EmitMemoryCall(Context, nameof(AMemory.ClearExclusive));
|
||||
}
|
||||
|
||||
public static void Dmb(AILEmitterCtx Context) => EmitBarrier(Context);
|
||||
public static void Dsb(AILEmitterCtx Context) => EmitBarrier(Context);
|
||||
|
||||
public static void Ldar(AILEmitterCtx Context) => EmitLdr(Context, AccessType.Ordered);
|
||||
public static void Ldaxr(AILEmitterCtx Context) => EmitLdr(Context, AccessType.OrderedEx);
|
||||
public static void Ldxr(AILEmitterCtx Context) => EmitLdr(Context, AccessType.Exclusive);
|
||||
public static void Ldxp(AILEmitterCtx Context) => EmitLdp(Context, AccessType.Exclusive);
|
||||
public static void Ldaxp(AILEmitterCtx Context) => EmitLdp(Context, AccessType.OrderedEx);
|
||||
|
||||
private static void EmitLdr(AILEmitterCtx Context, AccessType AccType)
|
||||
{
|
||||
EmitLoad(Context, AccType, false);
|
||||
}
|
||||
|
||||
private static void EmitLdp(AILEmitterCtx Context, AccessType AccType)
|
||||
{
|
||||
EmitLoad(Context, AccType, true);
|
||||
}
|
||||
|
||||
private static void EmitLoad(AILEmitterCtx Context, AccessType AccType, bool Pair)
|
||||
{
|
||||
AOpCodeMemEx Op = (AOpCodeMemEx)Context.CurrOp;
|
||||
|
||||
Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
|
||||
Context.EmitLdint(Op.Rn);
|
||||
|
||||
EmitReadZxCall(Context, Op.Size);
|
||||
|
||||
Context.EmitStintzr(Op.Rt);
|
||||
|
||||
if (Pair)
|
||||
{
|
||||
Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
|
||||
Context.EmitLdint(Op.Rn);
|
||||
Context.EmitLdc_I(8 << Op.Size);
|
||||
|
||||
Context.Emit(OpCodes.Add);
|
||||
|
||||
EmitReadZxCall(Context, Op.Size);
|
||||
|
||||
Context.EmitStintzr(Op.Rt2);
|
||||
}
|
||||
|
||||
if (AccType.HasFlag(AccessType.Exclusive))
|
||||
{
|
||||
EmitMemoryCall(Context, nameof(AMemory.SetExclusive), Op.Rn);
|
||||
}
|
||||
|
||||
if (AccType.HasFlag(AccessType.Ordered))
|
||||
{
|
||||
EmitBarrier(Context);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Pfrm(AILEmitterCtx Context)
|
||||
{
|
||||
//Memory Prefetch, execute as no-op.
|
||||
}
|
||||
|
||||
public static void Stlr(AILEmitterCtx Context) => EmitStr(Context, AccessType.Ordered);
|
||||
public static void Stlxr(AILEmitterCtx Context) => EmitStr(Context, AccessType.OrderedEx);
|
||||
public static void Stxr(AILEmitterCtx Context) => EmitStr(Context, AccessType.Exclusive);
|
||||
public static void Stxp(AILEmitterCtx Context) => EmitStp(Context, AccessType.Exclusive);
|
||||
public static void Stlxp(AILEmitterCtx Context) => EmitStp(Context, AccessType.OrderedEx);
|
||||
|
||||
private static void EmitStr(AILEmitterCtx Context, AccessType AccType)
|
||||
{
|
||||
EmitStore(Context, AccType, false);
|
||||
}
|
||||
|
||||
private static void EmitStp(AILEmitterCtx Context, AccessType AccType)
|
||||
{
|
||||
EmitStore(Context, AccType, true);
|
||||
}
|
||||
|
||||
private static void EmitStore(AILEmitterCtx Context, AccessType AccType, bool Pair)
|
||||
{
|
||||
AOpCodeMemEx Op = (AOpCodeMemEx)Context.CurrOp;
|
||||
|
||||
if (AccType.HasFlag(AccessType.Ordered))
|
||||
{
|
||||
EmitBarrier(Context);
|
||||
}
|
||||
|
||||
AILLabel LblEx = new AILLabel();
|
||||
AILLabel LblEnd = new AILLabel();
|
||||
|
||||
if (AccType.HasFlag(AccessType.Exclusive))
|
||||
{
|
||||
EmitMemoryCall(Context, nameof(AMemory.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(ATranslatedSub.MemoryArgIdx);
|
||||
Context.EmitLdint(Op.Rn);
|
||||
Context.EmitLdintzr(Op.Rt);
|
||||
|
||||
EmitWriteCall(Context, Op.Size);
|
||||
|
||||
if (Pair)
|
||||
{
|
||||
Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
|
||||
Context.EmitLdint(Op.Rn);
|
||||
Context.EmitLdc_I(8 << Op.Size);
|
||||
|
||||
Context.Emit(OpCodes.Add);
|
||||
|
||||
Context.EmitLdintzr(Op.Rt2);
|
||||
|
||||
EmitWriteCall(Context, Op.Size);
|
||||
}
|
||||
|
||||
if (AccType.HasFlag(AccessType.Exclusive))
|
||||
{
|
||||
Context.EmitLdc_I8(0);
|
||||
Context.EmitStintzr(Op.Rs);
|
||||
|
||||
Clrex(Context);
|
||||
}
|
||||
|
||||
Context.MarkLabel(LblEnd);
|
||||
}
|
||||
|
||||
private static void EmitMemoryCall(AILEmitterCtx Context, string Name, int Rn = -1)
|
||||
{
|
||||
Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
|
||||
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
||||
|
||||
if (Rn != -1)
|
||||
{
|
||||
Context.EmitLdint(Rn);
|
||||
}
|
||||
|
||||
Context.EmitCall(typeof(AMemory), Name);
|
||||
}
|
||||
|
||||
private static void EmitBarrier(AILEmitterCtx 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));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue