diff --git a/Ryujinx/Cpu/ATranslator.cs b/Ryujinx/Cpu/ATranslator.cs index 74bb9bb79..caa6f8c71 100644 --- a/Ryujinx/Cpu/ATranslator.cs +++ b/Ryujinx/Cpu/ATranslator.cs @@ -38,7 +38,7 @@ namespace ChocolArm64 Position = TranslateSubroutine(Position).Execute(Thread.Registers, Thread.Memory); } } - while (Position != 0 && KeepRunning); + while (Position != 0 && KeepRunning); } public bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub) diff --git a/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs b/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs index ac9c43c37..92a39c6a6 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitAlu.cs @@ -60,6 +60,8 @@ namespace ChocolArm64.Instruction Context.Emit(OpCodes.And); + EmitZeroCVFlags(Context); + Context.EmitZNFlagCheck(); EmitDataStoreS(Context); @@ -79,6 +81,8 @@ namespace ChocolArm64.Instruction if (SetFlags) { + EmitZeroCVFlags(Context); + Context.EmitZNFlagCheck(); } @@ -334,6 +338,14 @@ namespace ChocolArm64.Instruction { Context.Emit(OpCodes.Conv_I4); } - } + } + + private static void EmitZeroCVFlags(AILEmitterCtx Context) + { + Context.EmitLdc_I4(0); + Context.EmitLdc_I4(0); + Context.EmitStflg((int)APState.VBit); + Context.EmitStflg((int)APState.CBit); + } } } \ No newline at end of file diff --git a/Ryujinx/Cpu/Instruction/AInstEmitSimdMemory.cs b/Ryujinx/Cpu/Instruction/AInstEmitSimdMemory.cs index d75db619e..fdf53e254 100644 --- a/Ryujinx/Cpu/Instruction/AInstEmitSimdMemory.cs +++ b/Ryujinx/Cpu/Instruction/AInstEmitSimdMemory.cs @@ -1,6 +1,7 @@ using ChocolArm64.Decoder; using ChocolArm64.State; using ChocolArm64.Translation; +using System; using System.Reflection.Emit; using static ChocolArm64.Instruction.AInstEmitMemoryHelper; @@ -85,45 +86,73 @@ namespace ChocolArm64.Instruction { AOpCodeSimdMemSs Op = (AOpCodeSimdMemSs)Context.CurrOp; - //TODO: Replicate mode. - int Offset = 0; - for (int SElem = 0; SElem < Op.SElems; SElem++) + void EmitMemAddress() { - int Rt = (Op.Rt + SElem) & 0x1f; + Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); + Context.EmitLdint(Op.Rn); + Context.EmitLdc_I8(Offset); - if (IsLoad) + Context.Emit(OpCodes.Add); + } + + if (Op.Replicate) + { + //Only loads uses the replicate mode. + if (!IsLoad) { - Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); - Context.EmitLdint(Op.Rn); - Context.EmitLdc_I8(Offset); + throw new InvalidOperationException(); + } - Context.Emit(OpCodes.Add); + int Bytes = Context.CurrOp.GetBitsCount() >> 3; - EmitReadZxCall(Context, Op.Size); + for (int SElem = 0; SElem < Op.SElems; SElem++) + { + int Rt = (Op.Rt + SElem) & 0x1f; - EmitVectorInsert(Context, Rt, Op.Index, Op.Size); + for (int Index = 0; Index < (Bytes >> Op.Size); Index++) + { + EmitMemAddress(); + + EmitReadZxCall(Context, Op.Size); + + EmitVectorInsert(Context, Rt, Index, Op.Size); + } if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Rt); } + + Offset += 1 << Op.Size; } - else + } + else + { + for (int SElem = 0; SElem < Op.SElems; SElem++) { - Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); - Context.EmitLdint(Op.Rn); - Context.EmitLdc_I8(Offset); + int Rt = (Op.Rt + SElem) & 0x1f; - Context.Emit(OpCodes.Add); + if (IsLoad) + { + EmitMemAddress(); - EmitVectorExtractZx(Context, Rt, Op.Index, Op.Size); + EmitReadZxCall(Context, Op.Size); - EmitWriteCall(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; } - - Offset += 1 << Op.Size; } if (Op.WBack) diff --git a/Ryujinx/Ui/Program.cs b/Ryujinx/Ui/Program.cs index 2f29411a9..cc940aff6 100644 --- a/Ryujinx/Ui/Program.cs +++ b/Ryujinx/Ui/Program.cs @@ -2,6 +2,7 @@ using Gal.OpenGL; using System; using System.IO; +using ChocolArm64; namespace Ryujinx {