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/InstEmitMemory.cs | 252 +++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 ChocolArm64/Instructions/InstEmitMemory.cs (limited to 'ChocolArm64/Instructions/InstEmitMemory.cs') diff --git a/ChocolArm64/Instructions/InstEmitMemory.cs b/ChocolArm64/Instructions/InstEmitMemory.cs new file mode 100644 index 00000000..96e45b3f --- /dev/null +++ b/ChocolArm64/Instructions/InstEmitMemory.cs @@ -0,0 +1,252 @@ +using ChocolArm64.Decoders; +using ChocolArm64.Translation; +using System.Reflection.Emit; + +using static ChocolArm64.Instructions.InstEmitMemoryHelper; + +namespace ChocolArm64.Instructions +{ + static partial class InstEmit + { + public static void Adr(ILEmitterCtx context) + { + OpCodeAdr64 op = (OpCodeAdr64)context.CurrOp; + + context.EmitLdc_I(op.Position + op.Imm); + context.EmitStintzr(op.Rd); + } + + public static void Adrp(ILEmitterCtx context) + { + OpCodeAdr64 op = (OpCodeAdr64)context.CurrOp; + + context.EmitLdc_I((op.Position & ~0xfffL) + (op.Imm << 12)); + context.EmitStintzr(op.Rd); + } + + public static void Ldr(ILEmitterCtx context) => EmitLdr(context, false); + public static void Ldrs(ILEmitterCtx context) => EmitLdr(context, true); + + private static void EmitLdr(ILEmitterCtx context, bool signed) + { + OpCodeMem64 op = (OpCodeMem64)context.CurrOp; + + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + + EmitLoadAddress(context); + + if (signed && op.Extend64) + { + EmitReadSx64Call(context, op.Size); + } + else if (signed) + { + EmitReadSx32Call(context, op.Size); + } + else + { + EmitReadZxCall(context, op.Size); + } + + if (op is IOpCodeSimd64) + { + context.EmitStvec(op.Rt); + } + else + { + context.EmitStintzr(op.Rt); + } + + EmitWBackIfNeeded(context); + } + + public static void LdrLit(ILEmitterCtx context) + { + IOpCodeLit64 op = (IOpCodeLit64)context.CurrOp; + + if (op.Prefetch) + { + return; + } + + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + context.EmitLdc_I8(op.Imm); + + if (op.Signed) + { + EmitReadSx64Call(context, op.Size); + } + else + { + EmitReadZxCall(context, op.Size); + } + + if (op is IOpCodeSimd64) + { + context.EmitStvec(op.Rt); + } + else + { + context.EmitStint(op.Rt); + } + } + + public static void Ldp(ILEmitterCtx context) + { + OpCodeMemPair64 op = (OpCodeMemPair64)context.CurrOp; + + void EmitReadAndStore(int rt) + { + if (op.Extend64) + { + EmitReadSx64Call(context, op.Size); + } + else + { + EmitReadZxCall(context, op.Size); + } + + if (op is IOpCodeSimd64) + { + context.EmitStvec(rt); + } + else + { + context.EmitStintzr(rt); + } + } + + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + + EmitLoadAddress(context); + + EmitReadAndStore(op.Rt); + + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + context.EmitLdtmp(); + context.EmitLdc_I8(1 << op.Size); + + context.Emit(OpCodes.Add); + + EmitReadAndStore(op.Rt2); + + EmitWBackIfNeeded(context); + } + + public static void Str(ILEmitterCtx context) + { + OpCodeMem64 op = (OpCodeMem64)context.CurrOp; + + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + + EmitLoadAddress(context); + + if (op is IOpCodeSimd64) + { + context.EmitLdvec(op.Rt); + } + else + { + context.EmitLdintzr(op.Rt); + } + + EmitWriteCall(context, op.Size); + + EmitWBackIfNeeded(context); + } + + public static void Stp(ILEmitterCtx context) + { + OpCodeMemPair64 op = (OpCodeMemPair64)context.CurrOp; + + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + + EmitLoadAddress(context); + + if (op is IOpCodeSimd64) + { + context.EmitLdvec(op.Rt); + } + else + { + context.EmitLdintzr(op.Rt); + } + + EmitWriteCall(context, op.Size); + + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + context.EmitLdtmp(); + context.EmitLdc_I8(1 << op.Size); + + context.Emit(OpCodes.Add); + + if (op is IOpCodeSimd64) + { + context.EmitLdvec(op.Rt2); + } + else + { + context.EmitLdintzr(op.Rt2); + } + + EmitWriteCall(context, op.Size); + + EmitWBackIfNeeded(context); + } + + private static void EmitLoadAddress(ILEmitterCtx context) + { + switch (context.CurrOp) + { + case OpCodeMemImm64 op: + context.EmitLdint(op.Rn); + + if (!op.PostIdx) + { + //Pre-indexing. + context.EmitLdc_I(op.Imm); + + context.Emit(OpCodes.Add); + } + break; + + case OpCodeMemReg64 op: + context.EmitLdint(op.Rn); + context.EmitLdintzr(op.Rm); + context.EmitCast(op.IntType); + + if (op.Shift) + { + context.EmitLsl(op.Size); + } + + context.Emit(OpCodes.Add); + break; + } + + //Save address to Scratch var since the register value may change. + context.Emit(OpCodes.Dup); + + context.EmitSttmp(); + } + + private static void EmitWBackIfNeeded(ILEmitterCtx context) + { + //Check whenever the current OpCode has post-indexed write back, if so write it. + //Note: AOpCodeMemPair inherits from AOpCodeMemImm, so this works for both. + if (context.CurrOp is OpCodeMemImm64 op && op.WBack) + { + context.EmitLdtmp(); + + if (op.PostIdx) + { + context.EmitLdc_I(op.Imm); + + context.Emit(OpCodes.Add); + } + + context.EmitStint(op.Rn); + } + } + } +} \ No newline at end of file -- cgit v1.2.3