diff options
| author | Alex Barney <thealexbarney@gmail.com> | 2018-10-30 19:43:02 -0600 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-10-30 22:43:02 -0300 |
| commit | 9cb57fb4bb3bbae0ae052a5af4a96a49fc5d864d (patch) | |
| tree | 0c97425aeb311c142bc92a6fcc503cb2c07d4376 /ChocolArm64/Instructions/InstEmitSimdMemory.cs | |
| parent | 5a87e58183578f5b84ca8d01cbb76aed11820f78 (diff) | |
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
Diffstat (limited to 'ChocolArm64/Instructions/InstEmitSimdMemory.cs')
| -rw-r--r-- | ChocolArm64/Instructions/InstEmitSimdMemory.cs | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/ChocolArm64/Instructions/InstEmitSimdMemory.cs b/ChocolArm64/Instructions/InstEmitSimdMemory.cs new file mode 100644 index 00000000..eb053257 --- /dev/null +++ b/ChocolArm64/Instructions/InstEmitSimdMemory.cs @@ -0,0 +1,185 @@ +using ChocolArm64.Decoders; +using ChocolArm64.State; +using ChocolArm64.Translation; +using System; +using System.Reflection.Emit; + +using static ChocolArm64.Instructions.InstEmitMemoryHelper; +using static ChocolArm64.Instructions.InstEmitSimdHelper; + +namespace ChocolArm64.Instructions +{ + static partial class InstEmit + { + public static void Ld__Vms(ILEmitterCtx context) + { + EmitSimdMemMs(context, isLoad: true); + } + + public static void Ld__Vss(ILEmitterCtx context) + { + EmitSimdMemSs(context, isLoad: true); + } + + public static void St__Vms(ILEmitterCtx context) + { + EmitSimdMemMs(context, isLoad: false); + } + + public static void St__Vss(ILEmitterCtx context) + { + EmitSimdMemSs(context, isLoad: false); + } + + private static void EmitSimdMemMs(ILEmitterCtx context, bool isLoad) + { + OpCodeSimdMemMs64 op = (OpCodeSimdMemMs64)context.CurrOp; + + int offset = 0; + + for (int rep = 0; rep < op.Reps; rep++) + for (int elem = 0; elem < op.Elems; elem++) + for (int sElem = 0; sElem < op.SElems; sElem++) + { + int rtt = (op.Rt + rep + sElem) & 0x1f; + + if (isLoad) + { + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + context.EmitLdint(op.Rn); + context.EmitLdc_I8(offset); + + context.Emit(OpCodes.Add); + + EmitReadZxCall(context, op.Size); + + EmitVectorInsert(context, rtt, elem, op.Size); + + if (op.RegisterSize == RegisterSize.Simd64 && elem == op.Elems - 1) + { + EmitVectorZeroUpper(context, rtt); + } + } + else + { + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + context.EmitLdint(op.Rn); + context.EmitLdc_I8(offset); + + context.Emit(OpCodes.Add); + + EmitVectorExtractZx(context, rtt, elem, op.Size); + + EmitWriteCall(context, op.Size); + } + + offset += 1 << op.Size; + } + + if (op.WBack) + { + EmitSimdMemWBack(context, offset); + } + } + + private static void EmitSimdMemSs(ILEmitterCtx context, bool isLoad) + { + OpCodeSimdMemSs64 op = (OpCodeSimdMemSs64)context.CurrOp; + + int offset = 0; + + void EmitMemAddress() + { + context.EmitLdarg(TranslatedSub.MemoryArgIdx); + context.EmitLdint(op.Rn); + context.EmitLdc_I8(offset); + + context.Emit(OpCodes.Add); + } + + if (op.Replicate) + { + //Only loads uses the replicate mode. + if (!isLoad) + { + throw new InvalidOperationException(); + } + + int bytes = op.GetBitsCount() >> 3; + int elems = bytes >> op.Size; + + for (int sElem = 0; sElem < op.SElems; sElem++) + { + int rt = (op.Rt + sElem) & 0x1f; + + for (int index = 0; index < elems; index++) + { + EmitMemAddress(); + + EmitReadZxCall(context, op.Size); + + EmitVectorInsert(context, rt, index, op.Size); + } + + if (op.RegisterSize == RegisterSize.Simd64) + { + EmitVectorZeroUpper(context, rt); + } + + offset += 1 << op.Size; + } + } + else + { + for (int sElem = 0; sElem < op.SElems; sElem++) + { + int rt = (op.Rt + sElem) & 0x1f; + + if (isLoad) + { + EmitMemAddress(); + + EmitReadZxCall(context, op.Size); + + EmitVectorInsert(context, rt, op.Index, op.Size); + } + else + { + EmitMemAddress(); + + EmitVectorExtractZx(context, rt, op.Index, op.Size); + + EmitWriteCall(context, op.Size); + } + + offset += 1 << op.Size; + } + } + + if (op.WBack) + { + EmitSimdMemWBack(context, offset); + } + } + + private static void EmitSimdMemWBack(ILEmitterCtx context, int offset) + { + OpCodeMemReg64 op = (OpCodeMemReg64)context.CurrOp; + + context.EmitLdint(op.Rn); + + if (op.Rm != CpuThreadState.ZrIndex) + { + context.EmitLdint(op.Rm); + } + else + { + context.EmitLdc_I8(offset); + } + + context.Emit(OpCodes.Add); + + context.EmitStint(op.Rn); + } + } +}
\ No newline at end of file |
