mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2024-11-24 07:34:15 +00:00
Add FVCTZS (fixed point variant) and LD1 (single structure variant) instructions
This commit is contained in:
parent
ebbccfcdbf
commit
6a3aa6cd88
9 changed files with 279 additions and 22 deletions
|
@ -153,6 +153,7 @@ namespace ChocolArm64
|
||||||
Set("x0011110xx101000000000xxxxxxxxxx", AInstEmit.Fcvtps_S, typeof(AOpCodeSimdCvt));
|
Set("x0011110xx101000000000xxxxxxxxxx", AInstEmit.Fcvtps_S, typeof(AOpCodeSimdCvt));
|
||||||
Set("x0011110xx111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_S, typeof(AOpCodeSimdCvt));
|
Set("x0011110xx111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_S, typeof(AOpCodeSimdCvt));
|
||||||
Set("0x0011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd));
|
Set("0x0011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd));
|
||||||
|
Set("0x0011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzs_V_Fix, typeof(AOpCodeSimdShImm));
|
||||||
Set("x0011110xx111001000000xxxxxxxxxx", AInstEmit.Fcvtzu_S, typeof(AOpCodeSimdCvt));
|
Set("x0011110xx111001000000xxxxxxxxxx", AInstEmit.Fcvtzu_S, typeof(AOpCodeSimdCvt));
|
||||||
Set("0x1011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimd));
|
Set("0x1011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimd));
|
||||||
Set("0x1011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzu_V_Fix, typeof(AOpCodeSimdShImm));
|
Set("0x1011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzu_V_Fix, typeof(AOpCodeSimdShImm));
|
||||||
|
@ -186,8 +187,10 @@ namespace ChocolArm64
|
||||||
Set("0x0011101x1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg));
|
Set("0x0011101x1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg));
|
||||||
Set("01001110000xxxxx000111xxxxxxxxxx", AInstEmit.Ins_Gp, typeof(AOpCodeSimdIns));
|
Set("01001110000xxxxx000111xxxxxxxxxx", AInstEmit.Ins_Gp, typeof(AOpCodeSimdIns));
|
||||||
Set("01101110000xxxxx0xxxx1xxxxxxxxxx", AInstEmit.Ins_V, typeof(AOpCodeSimdIns));
|
Set("01101110000xxxxx0xxxx1xxxxxxxxxx", AInstEmit.Ins_V, typeof(AOpCodeSimdIns));
|
||||||
Set("0x00110001000000xxxxxxxxxxxxxxxx", AInstEmit.Ld__V, typeof(AOpCodeSimdMemMult));
|
Set("0x00110001000000xxxxxxxxxxxxxxxx", AInstEmit.Ld__Vms, typeof(AOpCodeSimdMemMs));
|
||||||
Set("0x001100110xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ld__V, typeof(AOpCodeSimdMemMult));
|
Set("0x001100110xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ld__Vms, typeof(AOpCodeSimdMemMs));
|
||||||
|
Set("0x00110101000000xx0xxxxxxxxxxxxx", AInstEmit.Ld__Vss, typeof(AOpCodeSimdMemSs));
|
||||||
|
Set("0x001101110xxxxxxx0xxxxxxxxxxxxx", AInstEmit.Ld__Vss, typeof(AOpCodeSimdMemSs));
|
||||||
Set("xx10110xx1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldp, typeof(AOpCodeSimdMemPair));
|
Set("xx10110xx1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldp, typeof(AOpCodeSimdMemPair));
|
||||||
Set("xx111100x10xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
Set("xx111100x10xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
||||||
Set("xx111100x10xxxxxxxxx01xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
Set("xx111100x10xxxxxxxxx01xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
||||||
|
@ -218,8 +221,8 @@ namespace ChocolArm64
|
||||||
Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
|
Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
|
||||||
Set("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
|
Set("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
|
||||||
Set("0x0011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm));
|
Set("0x0011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm));
|
||||||
Set("0x00110000000000xxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMult));
|
Set("0x00110000000000xxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMs));
|
||||||
Set("0x001100100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMult));
|
Set("0x001100100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMs));
|
||||||
Set("xx10110xx0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Stp, typeof(AOpCodeSimdMemPair));
|
Set("xx10110xx0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Stp, typeof(AOpCodeSimdMemPair));
|
||||||
Set("xx111100x00xxxxxxxxx00xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
Set("xx111100x00xxxxxxxxx00xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
||||||
Set("xx111100x00xxxxxxxxx01xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
Set("xx111100x00xxxxxxxxx01xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
||||||
|
|
4
Ryujinx/Cpu/AOptimizations.cs
Normal file
4
Ryujinx/Cpu/AOptimizations.cs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
public static class AOptimizations
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ using ChocolArm64.State;
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
namespace ChocolArm64.Decoder
|
||||||
{
|
{
|
||||||
class AOpCodeSimdMemMult : AOpCode, IAOpCodeSimd
|
class AOpCodeSimdMemMs : AOpCode, IAOpCodeSimd
|
||||||
{
|
{
|
||||||
public int Rt { get; private set; }
|
public int Rt { get; private set; }
|
||||||
public int Rn { get; private set; }
|
public int Rn { get; private set; }
|
||||||
|
@ -14,7 +14,7 @@ namespace ChocolArm64.Decoder
|
||||||
public int Elems { get; private set; }
|
public int Elems { get; private set; }
|
||||||
public bool WBack { get; private set; }
|
public bool WBack { get; private set; }
|
||||||
|
|
||||||
public AOpCodeSimdMemMult(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeSimdMemMs(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
||||||
{
|
{
|
||||||
switch ((OpCode >> 12) & 0xf)
|
switch ((OpCode >> 12) & 0xf)
|
||||||
{
|
{
|
104
Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs
Normal file
104
Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
using ChocolArm64.Instruction;
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoder
|
||||||
|
{
|
||||||
|
class AOpCodeSimdMemSs : AOpCode, IAOpCodeSimd
|
||||||
|
{
|
||||||
|
public int Rt { get; private set; }
|
||||||
|
public int Rn { get; private set; }
|
||||||
|
public int Size { get; private set; }
|
||||||
|
public int Rm { get; private set; }
|
||||||
|
public int SElems { get; private set; }
|
||||||
|
public int Index { get; private set; }
|
||||||
|
public bool Replicate { get; private set; }
|
||||||
|
public bool WBack { get; private set; }
|
||||||
|
|
||||||
|
public AOpCodeSimdMemSs(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
||||||
|
{
|
||||||
|
int Size = (OpCode >> 10) & 3;
|
||||||
|
int S = (OpCode >> 12) & 1;
|
||||||
|
int SElems = (OpCode >> 12) & 2;
|
||||||
|
int Scale = (OpCode >> 14) & 3;
|
||||||
|
int L = (OpCode >> 22) & 1;
|
||||||
|
int Q = (OpCode >> 30) & 1;
|
||||||
|
|
||||||
|
SElems |= (OpCode >> 21) & 1;
|
||||||
|
|
||||||
|
SElems++;
|
||||||
|
|
||||||
|
int Index = (Q << 3) | (S << 2) | Size;
|
||||||
|
|
||||||
|
switch (Scale)
|
||||||
|
{
|
||||||
|
case 0: Index >>= 0; break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
if ((Index & 1) != 0)
|
||||||
|
{
|
||||||
|
Inst = AInst.Undefined;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Index >>= 1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
if ((Index & 2) != 0 ||
|
||||||
|
((Index & 1) != 0 && S != 0))
|
||||||
|
{
|
||||||
|
Inst = AInst.Undefined;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Index & 1) != 0)
|
||||||
|
{
|
||||||
|
Index >>= 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Index >>= 2;
|
||||||
|
|
||||||
|
Scale = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
if (L == 0 || S != 0)
|
||||||
|
{
|
||||||
|
Inst = AInst.Undefined;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale = Size;
|
||||||
|
|
||||||
|
Replicate = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.SElems = SElems;
|
||||||
|
this.Size = Scale;
|
||||||
|
|
||||||
|
Rt = (OpCode >> 0) & 0x1f;
|
||||||
|
Rn = (OpCode >> 5) & 0x1f;
|
||||||
|
Rm = (OpCode >> 16) & 0x1f;
|
||||||
|
WBack = ((OpCode >> 23) & 0x1) != 0;
|
||||||
|
|
||||||
|
RegisterSize = Q != 0
|
||||||
|
? ARegisterSize.SIMD128
|
||||||
|
: ARegisterSize.SIMD64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -122,6 +122,7 @@ namespace ChocolArm64.Instruction
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
Context.EmitLdvec(Op.Rn);
|
Context.EmitLdvec(Op.Rn);
|
||||||
|
Context.EmitLdc_I4(0);
|
||||||
Context.EmitLdc_I4(Op.SizeF);
|
Context.EmitLdc_I4(Op.SizeF);
|
||||||
|
|
||||||
ASoftFallback.EmitCall(Context,
|
ASoftFallback.EmitCall(Context,
|
||||||
|
@ -131,6 +132,21 @@ namespace ChocolArm64.Instruction
|
||||||
Context.EmitStvec(Op.Rd);
|
Context.EmitStvec(Op.Rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Fcvtzs_V_Fix(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
|
||||||
|
Context.EmitLdvec(Op.Rn);
|
||||||
|
Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm);
|
||||||
|
Context.EmitLdc_I4(Op.Size - 2);
|
||||||
|
|
||||||
|
ASoftFallback.EmitCall(Context,
|
||||||
|
nameof(ASoftFallback.Fcvtzs_V64),
|
||||||
|
nameof(ASoftFallback.Fcvtzs_V128));
|
||||||
|
|
||||||
|
Context.EmitStvec(Op.Rd);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Fcvtzu_V(AILEmitterCtx Context)
|
public static void Fcvtzu_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
@ -283,7 +299,8 @@ namespace ChocolArm64.Instruction
|
||||||
Context.EmitStvec(Op.Rd);
|
Context.EmitStvec(Op.Rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Ld__V(AILEmitterCtx Context) => EmitSimdMultLdSt(Context, IsLoad: true);
|
public static void Ld__Vms(AILEmitterCtx Context) => EmitSimdMemMs(Context, IsLoad: true);
|
||||||
|
public static void Ld__Vss(AILEmitterCtx Context) => EmitSimdMemSs(Context, IsLoad: true);
|
||||||
|
|
||||||
public static void Mla_V(AILEmitterCtx Context) => EmitVectorMla(Context);
|
public static void Mla_V(AILEmitterCtx Context) => EmitVectorMla(Context);
|
||||||
|
|
||||||
|
@ -391,7 +408,7 @@ namespace ChocolArm64.Instruction
|
||||||
EmitVectorImmBinarySx(Context, OpCodes.Shr, (8 << (Op.Size + 1)) - Op.Imm);
|
EmitVectorImmBinarySx(Context, OpCodes.Shr, (8 << (Op.Size + 1)) - Op.Imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void St__V(AILEmitterCtx Context) => EmitSimdMultLdSt(Context, IsLoad: false);
|
public static void St__V(AILEmitterCtx Context) => EmitSimdMemMs(Context, IsLoad: false);
|
||||||
|
|
||||||
public static void Sub_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.Sub);
|
public static void Sub_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.Sub);
|
||||||
|
|
||||||
|
@ -571,9 +588,9 @@ namespace ChocolArm64.Instruction
|
||||||
Context.EmitStvec(Op.Rd);
|
Context.EmitStvec(Op.Rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitSimdMultLdSt(AILEmitterCtx Context, bool IsLoad)
|
private static void EmitSimdMemMs(AILEmitterCtx Context, bool IsLoad)
|
||||||
{
|
{
|
||||||
AOpCodeSimdMemMult Op = (AOpCodeSimdMemMult)Context.CurrOp;
|
AOpCodeSimdMemMs Op = (AOpCodeSimdMemMs)Context.CurrOp;
|
||||||
|
|
||||||
int Offset = 0;
|
int Offset = 0;
|
||||||
|
|
||||||
|
@ -644,6 +661,79 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void EmitSimdMemSs(AILEmitterCtx Context, bool IsLoad)
|
||||||
|
{
|
||||||
|
AOpCodeSimdMemSs Op = (AOpCodeSimdMemSs)Context.CurrOp;
|
||||||
|
|
||||||
|
//TODO: Replicate mode.
|
||||||
|
|
||||||
|
int Offset = 0;
|
||||||
|
|
||||||
|
for (int SElem = 0; SElem < Op.SElems; SElem++)
|
||||||
|
{
|
||||||
|
int Rt = (Op.Rt + SElem) & 0x1f;
|
||||||
|
|
||||||
|
if (IsLoad)
|
||||||
|
{
|
||||||
|
Context.EmitLdvec(Rt);
|
||||||
|
Context.EmitLdc_I4(Op.Index);
|
||||||
|
Context.EmitLdc_I4(Op.Size);
|
||||||
|
Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
|
||||||
|
Context.EmitLdint(Op.Rn);
|
||||||
|
Context.EmitLdc_I8(Offset);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Add);
|
||||||
|
|
||||||
|
EmitReadZxCall(Context, Op.Size);
|
||||||
|
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InsertVec));
|
||||||
|
|
||||||
|
Context.EmitStvec(Rt);
|
||||||
|
|
||||||
|
if (Op.RegisterSize == ARegisterSize.SIMD64)
|
||||||
|
{
|
||||||
|
EmitVectorZeroUpper(Context, Rt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
|
||||||
|
Context.EmitLdint(Op.Rn);
|
||||||
|
Context.EmitLdc_I8(Offset);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Add);
|
||||||
|
|
||||||
|
Context.EmitLdvec(Rt);
|
||||||
|
Context.EmitLdc_I4(Op.Index);
|
||||||
|
Context.EmitLdc_I4(Op.Size);
|
||||||
|
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ExtractVec));
|
||||||
|
|
||||||
|
EmitWriteCall(Context, Op.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Offset += 1 << Op.Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Op.WBack)
|
||||||
|
{
|
||||||
|
Context.EmitLdint(Op.Rn);
|
||||||
|
|
||||||
|
if (Op.Rm != ARegisters.ZRIndex)
|
||||||
|
{
|
||||||
|
Context.EmitLdint(Op.Rm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Context.EmitLdc_I8(Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Add);
|
||||||
|
|
||||||
|
Context.EmitStint(Op.Rn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void EmitVectorAddv(AILEmitterCtx Context)
|
private static void EmitVectorAddv(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
|
@ -405,17 +405,17 @@ namespace ChocolArm64.Instruction
|
||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AVec Fcvtzs_V64(AVec Vector, int Size)
|
public static AVec Fcvtzs_V64(AVec Vector, int FBits, int Size)
|
||||||
{
|
{
|
||||||
return Fcvtzs_V(Vector, Size, 2);
|
return Fcvtzs_V(Vector, FBits, Size, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AVec Fcvtzs_V128(AVec Vector, int Size)
|
public static AVec Fcvtzs_V128(AVec Vector, int FBits, int Size)
|
||||||
{
|
{
|
||||||
return Fcvtzs_V(Vector, Size, 4);
|
return Fcvtzs_V(Vector, FBits, Size, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AVec Fcvtzs_V(AVec Vector, int Size, int Bytes)
|
private static AVec Fcvtzs_V(AVec Vector, int FBits, int Size, int Bytes)
|
||||||
{
|
{
|
||||||
AVec Res = new AVec();
|
AVec Res = new AVec();
|
||||||
|
|
||||||
|
@ -427,7 +427,7 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
float Value = Vector.ExtractSingle(Index);
|
float Value = Vector.ExtractSingle(Index);
|
||||||
|
|
||||||
Res = InsertSVec(Res, Index, Size + 2, SatSingleToInt32(Value));
|
Res = InsertSVec(Res, Index, Size + 2, SatSingleToInt32(Value, FBits));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -436,7 +436,7 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
double Value = Vector.ExtractDouble(Index);
|
double Value = Vector.ExtractDouble(Index);
|
||||||
|
|
||||||
Res = InsertSVec(Res, Index, Size + 2, SatDoubleToInt64(Value));
|
Res = InsertSVec(Res, Index, Size + 2, SatDoubleToInt64(Value, FBits));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using ChocolArm64.Exceptions;
|
||||||
using ChocolArm64.State;
|
using ChocolArm64.State;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -119,26 +120,46 @@ namespace ChocolArm64.Memory
|
||||||
|
|
||||||
public byte ReadByte(long Position)
|
public byte ReadByte(long Position)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||||
|
#endif
|
||||||
|
|
||||||
return *((byte*)(RamPtr + (uint)Position));
|
return *((byte*)(RamPtr + (uint)Position));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ushort ReadUInt16(long Position)
|
public ushort ReadUInt16(long Position)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||||
|
#endif
|
||||||
|
|
||||||
return *((ushort*)(RamPtr + (uint)Position));
|
return *((ushort*)(RamPtr + (uint)Position));
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ReadUInt32(long Position)
|
public uint ReadUInt32(long Position)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||||
|
#endif
|
||||||
|
|
||||||
return *((uint*)(RamPtr + (uint)Position));
|
return *((uint*)(RamPtr + (uint)Position));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong ReadUInt64(long Position)
|
public ulong ReadUInt64(long Position)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||||
|
#endif
|
||||||
|
|
||||||
return *((ulong*)(RamPtr + (uint)Position));
|
return *((ulong*)(RamPtr + (uint)Position));
|
||||||
}
|
}
|
||||||
|
|
||||||
public AVec ReadVector128(long Position)
|
public AVec ReadVector128(long Position)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||||
|
#endif
|
||||||
|
|
||||||
return new AVec()
|
return new AVec()
|
||||||
{
|
{
|
||||||
X0 = ReadUInt64(Position + 0),
|
X0 = ReadUInt64(Position + 0),
|
||||||
|
@ -153,33 +174,61 @@ namespace ChocolArm64.Memory
|
||||||
|
|
||||||
public void WriteByte(long Position, byte Value)
|
public void WriteByte(long Position, byte Value)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||||
|
#endif
|
||||||
|
|
||||||
*((byte*)(RamPtr + (uint)Position)) = Value;
|
*((byte*)(RamPtr + (uint)Position)) = Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteUInt16(long Position, ushort Value)
|
public void WriteUInt16(long Position, ushort Value)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||||
|
#endif
|
||||||
|
|
||||||
*((ushort*)(RamPtr + (uint)Position)) = Value;
|
*((ushort*)(RamPtr + (uint)Position)) = Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteUInt32(long Position, uint Value)
|
public void WriteUInt32(long Position, uint Value)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||||
|
#endif
|
||||||
|
|
||||||
*((uint*)(RamPtr + (uint)Position)) = Value;
|
*((uint*)(RamPtr + (uint)Position)) = Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteUInt64(long Position, ulong Value)
|
public void WriteUInt64(long Position, ulong Value)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||||
|
#endif
|
||||||
|
|
||||||
*((ulong*)(RamPtr + (uint)Position)) = Value;
|
*((ulong*)(RamPtr + (uint)Position)) = Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteVector128(long Position, AVec Value)
|
public void WriteVector128(long Position, AVec Value)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||||
|
#endif
|
||||||
|
|
||||||
WriteUInt64(Position + 0, Value.X0);
|
WriteUInt64(Position + 0, Value.X0);
|
||||||
WriteUInt64(Position + 8, Value.X1);
|
WriteUInt64(Position + 8, Value.X1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsPageCrossed(long Position, int Size)
|
private void EnsureAccessIsValid(long Position, AMemoryPerm Perm)
|
||||||
{
|
{
|
||||||
return (Position & AMemoryMgr.PageMask) + Size > AMemoryMgr.PageSize;
|
if (!Manager.IsMapped(Position))
|
||||||
|
{
|
||||||
|
throw new VmmPageFaultException(Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Manager.HasPermission(Position, Perm))
|
||||||
|
{
|
||||||
|
throw new VmmAccessViolationException(Position, Perm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -163,7 +163,7 @@ namespace ChocolArm64.Memory
|
||||||
{
|
{
|
||||||
while (Size > 0)
|
while (Size > 0)
|
||||||
{
|
{
|
||||||
if (!HasPTEntry(Position))
|
if (!IsMapped(Position))
|
||||||
{
|
{
|
||||||
long PhysPos = Allocator.Alloc(PageSize);
|
long PhysPos = Allocator.Alloc(PageSize);
|
||||||
|
|
||||||
|
@ -254,8 +254,13 @@ namespace ChocolArm64.Memory
|
||||||
return new AMemoryMapInfo(Start, Size, BaseEntry.Type, BaseEntry.Perm);
|
return new AMemoryMapInfo(Start, Size, BaseEntry.Type, BaseEntry.Perm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool HasPermission(long Position, AMemoryPerm Perm)
|
||||||
|
{
|
||||||
|
return GetPTEntry(Position).Perm.HasFlag(Perm);
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private bool HasPTEntry(long Position)
|
public bool IsMapped(long Position)
|
||||||
{
|
{
|
||||||
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
|
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -73,12 +73,14 @@ namespace Ryujinx.Loaders
|
||||||
MemoryType Type,
|
MemoryType Type,
|
||||||
AMemoryPerm Perm)
|
AMemoryPerm Perm)
|
||||||
{
|
{
|
||||||
Memory.Manager.MapPhys(Position, Data.Count, (int)Type, Perm);
|
Memory.Manager.MapPhys(Position, Data.Count, (int)Type, AMemoryPerm.Write);
|
||||||
|
|
||||||
for (int Index = 0; Index < Data.Count; Index++)
|
for (int Index = 0; Index < Data.Count; Index++)
|
||||||
{
|
{
|
||||||
Memory.WriteByte(Position + Index, Data[Index]);
|
Memory.WriteByte(Position + Index, Data[Index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Memory.Manager.Reprotect(Position, Data.Count, Perm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MapBss(long Position, long Size)
|
private void MapBss(long Position, long Size)
|
||||||
|
|
Loading…
Reference in a new issue