Pass memory manager type around

This commit is contained in:
Gabriel A 2024-01-04 17:42:33 -03:00
parent 133f7d10de
commit 98c16ed3b0
6 changed files with 119 additions and 97 deletions

View File

@ -1,3 +1,4 @@
using ARMeilleure.Memory;
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
using System;
using System.Collections.Generic;
@ -10,6 +11,8 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
public Assembler Arm64Assembler { get; }
public RegisterAllocator RegisterAllocator { get; }
public MemoryManagerType MemoryManagerType { get; }
private uint _instructionAddress;
public bool IsThumb { get; }
@ -26,11 +29,12 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
private bool _nzcvModified;
public CodeGenContext(CodeWriter codeWriter, Assembler arm64Assembler, RegisterAllocator registerAllocator, bool isThumb)
public CodeGenContext(CodeWriter codeWriter, Assembler arm64Assembler, RegisterAllocator registerAllocator, MemoryManagerType mmType, bool isThumb)
{
CodeWriter = codeWriter;
Arm64Assembler = arm64Assembler;
RegisterAllocator = registerAllocator;
MemoryManagerType = mmType;
_itConditions = new ArmCondition[4];
_pendingBranches = new();
IsThumb = isThumb;

View File

@ -21,6 +21,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{
public readonly CodeWriter Writer;
public readonly RegisterAllocator RegisterAllocator;
public readonly MemoryManagerType MemoryManagerType;
public readonly TailMerger TailMerger;
public readonly AddressTable<ulong> FuncTable;
public readonly IntPtr DispatchStubPointer;
@ -31,6 +32,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
public Context(
CodeWriter writer,
RegisterAllocator registerAllocator,
MemoryManagerType mmType,
TailMerger tailMerger,
AddressTable<ulong> funcTable,
RegisterSaveRestore registerSaveRestore,
@ -39,6 +41,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{
Writer = writer;
RegisterAllocator = registerAllocator;
MemoryManagerType = mmType;
TailMerger = tailMerger;
FuncTable = funcTable;
_registerSaveRestore = registerSaveRestore;
@ -232,7 +235,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
CodeWriter writer = new();
RegisterAllocator regAlloc = new();
Assembler asm = new(writer);
CodeGenContext cgContext = new(writer, asm, regAlloc, isThumb);
CodeGenContext cgContext = new(writer, asm, regAlloc, memoryManager.Type, isThumb);
ArmCondition lastCondition = ArmCondition.Al;
int lastConditionIp = 0;
@ -311,7 +314,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
TailMerger tailMerger = new();
Context context = new(writer, regAlloc, tailMerger, funcTable, rsr, dispatchStubPtr, memoryManager.PageTablePointer);
Context context = new(writer, regAlloc, memoryManager.Type, tailMerger, funcTable, rsr, dispatchStubPtr, memoryManager.PageTablePointer);
InstInfo lastInstruction = multiBlock.Blocks[^1].Instructions[^1];
bool lastInstIsConditional = GetCondition(lastInstruction, isThumb) != ArmCondition.Al;
@ -635,7 +638,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
ArmShiftType.Lsl,
halfword ? 1 : 0);
InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, asm, target.Operand, target.Operand);
InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, asm, target.Operand, target.Operand);
if (halfword)
{

View File

@ -1,3 +1,4 @@
using ARMeilleure.Memory;
using Ryujinx.Cpu.LightningJit.CodeGen;
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
using System;
@ -66,7 +67,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped();
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress);
EmitMemoryMultipleInstructionCore(
context,
@ -335,7 +336,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped();
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress);
EmitMemoryMultipleInstructionCore(
context,
@ -477,7 +478,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
offset = InstEmitCommon.Const(BitOperations.PopCount(registerList) * 4 - 4);
WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, baseAddress, offset, false, ArmShiftType.Lsl, 0);
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand);
EmitMemoryMultipleInstructionCore(
context,
@ -516,12 +517,12 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
if (w && !writesToRn)
{
WriteAddShiftOffset(context.Arm64Assembler, baseAddress, baseAddress, offset, false, ArmShiftType.Lsl, 0);
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress);
}
else
{
WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, baseAddress, offset, false, ArmShiftType.Lsl, 0);
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand);
}
EmitMemoryMultipleInstructionCore(
@ -554,7 +555,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
Operand offset = InstEmitCommon.Const(4);
WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, baseAddress, offset, true, ArmShiftType.Lsl, 0);
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand);
EmitMemoryMultipleInstructionCore(
context,
@ -663,7 +664,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped();
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand);
action(rtOperand, tempRegister.Operand);
}
@ -676,7 +677,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped();
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand);
action(rtOperand, rt2Operand, tempRegister.Operand);
}
@ -746,17 +747,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
if (offset.Kind == OperandKind.Constant && offset.Value == 0)
{
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress);
}
else if (offset.Kind == OperandKind.Constant && CanFoldDWordOffset(signedOffs))
else if (offset.Kind == OperandKind.Constant && CanFoldDWordOffset(context.MemoryManagerType, signedOffs))
{
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress);
offs = signedOffs;
}
else
{
WriteAddShiftOffset(asm, tempRegister.Operand, baseAddress, offset, add, ArmShiftType.Lsl, 0);
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, tempRegister.Operand);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, tempRegister.Operand);
}
action(rt, rt2, tempRegister.Operand, offs);
@ -767,7 +768,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped();
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress);
action(rt, rt2, tempRegister.Operand, 0);
@ -784,7 +785,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
// If Rt and Rn are the same register, ensure we perform the write back after the read/write.
WriteAddShiftOffset(asm, tempRegister.Operand, baseAddress, offset, add, ArmShiftType.Lsl, 0);
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, tempRegister.Operand);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, tempRegister.Operand);
action(rt, rt2, tempRegister.Operand, 0);
@ -793,7 +794,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
else
{
WriteAddShiftOffset(asm, baseAddress, baseAddress, offset, add, ArmShiftType.Lsl, 0);
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress);
action(rt, rt2, tempRegister.Operand, 0);
}
@ -808,7 +809,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped();
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand);
action(rdOperand, rtOperand, tempRegister.Operand);
}
@ -822,7 +823,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped();
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand);
action(rdOperand, rtOperand, rt2Operand, tempRegister.Operand);
}
@ -856,17 +857,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
if (offset.Kind == OperandKind.Constant && offset.Value == 0)
{
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress);
}
else if (offset.Kind == OperandKind.Constant && shift == 0 && CanFoldOffset(signedOffs, scale, writeInstUnscaled != null, out unscaled))
else if (offset.Kind == OperandKind.Constant && shift == 0 && CanFoldOffset(context.MemoryManagerType, signedOffs, scale, writeInstUnscaled != null, out unscaled))
{
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress);
offs = signedOffs;
}
else
{
WriteAddShiftOffset(asm, tempRegister.Operand, baseAddress, offset, add, shiftType, shift);
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, tempRegister.Operand);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, tempRegister.Operand);
}
if (unscaled)
@ -891,7 +892,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{
using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped();
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress);
WriteAddShiftOffset(asm, baseAddress, baseAddress, offset, add, shiftType, shift);
writeInst(rt, tempRegister.Operand, 0);
@ -901,7 +902,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped();
using ScopedRegister tempRegister2 = regAlloc.AllocateTempGprRegisterScoped();
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress);
WriteAddShiftOffset(asm, tempRegister2.Operand, baseAddress, offset, add, shiftType, shift);
writeInst(rt, tempRegister.Operand, 0);
@ -913,7 +914,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{
using ScopedRegister tempRegister = regAlloc.AllocateTempGprRegisterScoped();
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress);
writeInst(rt, tempRegister.Operand, 0);
@ -931,7 +932,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
// If Rt and Rn are the same register, ensure we perform the write back after the read/write.
WriteAddShiftOffset(asm, tempRegister.Operand, baseAddress, offset, add, shiftType, shift);
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, tempRegister.Operand);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, tempRegister.Operand);
writeInst(rt, tempRegister.Operand, 0);
@ -940,7 +941,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
else
{
WriteAddShiftOffset(asm, baseAddress, baseAddress, offset, add, shiftType, shift);
WriteAddressTranslation(regAlloc, asm, tempRegister.Operand, baseAddress);
WriteAddressTranslation(context.MemoryManagerType, regAlloc, asm, tempRegister.Operand, baseAddress);
writeInst(rt, tempRegister.Operand, 0);
}
@ -974,7 +975,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped();
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress);
action(rtOperand, tempRegister.Operand, 0);
}
@ -1003,7 +1004,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped();
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress);
action(rtOperand, rt2Operand, tempRegister.Operand, 0);
}
@ -1020,17 +1021,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
if (imm == 0)
{
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand);
}
else if (CanFoldOffset(signedOffs, 3, true, out unscaled))
else if (CanFoldOffset(context.MemoryManagerType, signedOffs, 3, true, out unscaled))
{
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, rnOperand);
offs = signedOffs;
}
else
{
WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, rnOperand, InstEmitCommon.Const((int)imm), u, ArmShiftType.Lsl, 0);
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand);
}
if (unscaled)
@ -1051,7 +1052,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped();
WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, rnOperand, rmOperand, u, (ArmShiftType)sType, (int)shift);
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand);
context.Arm64Assembler.PrfmI(tempRegister.Operand, 0, (uint)type, 0, 0);
}
@ -1071,14 +1072,19 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
using ScopedRegister tempRegister = context.RegisterAllocator.AllocateTempGprRegisterScoped();
WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress);
WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, targetAddress);
context.Arm64Assembler.PrfmI(tempRegister.Operand, 0, (uint)type, 0, 0);
}
public static bool CanFoldOffset(int offset, int scale, bool hasUnscaled, out bool unscaled)
public static bool CanFoldOffset(MemoryManagerType mmType, int offset, int scale, bool hasUnscaled, out bool unscaled)
{
// TODO: Check if the memory manager mode also works with folded offsets.
if (mmType != MemoryManagerType.HostMappedUnsafe)
{
unscaled = false;
return false;
}
int mask = (1 << scale) - 1;
@ -1098,21 +1104,24 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
return unscaled;
}
private static bool CanFoldDWordOffset(int offset)
private static bool CanFoldDWordOffset(MemoryManagerType mmType, int offset)
{
// TODO: Check if the memory manager mode also works with folded offsets.
if (mmType != MemoryManagerType.HostMappedUnsafe)
{
return false;
}
return offset >= 0 && offset < 0x40 && (offset & 3) == 0;
}
private static void WriteAddressTranslation(RegisterAllocator regAlloc, in Assembler asm, Operand destination, uint guestAddress)
private static void WriteAddressTranslation(MemoryManagerType mmType, RegisterAllocator regAlloc, in Assembler asm, Operand destination, uint guestAddress)
{
asm.Mov(destination, guestAddress);
WriteAddressTranslation(regAlloc, asm, destination, destination);
WriteAddressTranslation(mmType, regAlloc, asm, destination, destination);
}
public static void WriteAddressTranslation(RegisterAllocator regAlloc, in Assembler asm, Operand destination, Operand guestAddress)
public static void WriteAddressTranslation(MemoryManagerType mmType, RegisterAllocator regAlloc, in Assembler asm, Operand destination, Operand guestAddress)
{
Operand destination64 = new(destination.Kind, OperandType.I64, destination.Value);
Operand basePointer = new(regAlloc.FixedPageTableRegister, RegisterType.Integer, OperandType.I64);

View File

@ -258,17 +258,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
if (wBack)
{
InstEmitMemory.WriteAddShiftOffset(context.Arm64Assembler, baseAddress, baseAddress, offset, false, ArmShiftType.Lsl, 0);
InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress);
InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress);
}
else
{
InstEmitMemory.WriteAddShiftOffset(context.Arm64Assembler, tempRegister.Operand, baseAddress, offset, false, ArmShiftType.Lsl, 0);
InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand);
InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, tempRegister.Operand);
}
}
else
{
InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress);
InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, tempRegister.Operand, baseAddress);
}
EmitMemoryMultipleInstructionCore(context, tempRegister.Operand, rd, registerCount, singleRegs, isStore);
@ -402,7 +402,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
context.Arm64Assembler.Mov(address.Operand, (context.Pc & ~3u) + (uint)offs);
InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, address.Operand, address.Operand);
InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, address.Operand, address.Operand);
offs = 0;
}
@ -410,9 +410,9 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{
Operand rnOperand = context.RegisterAllocator.RemapGprRegister((int)rn);
if (InstEmitMemory.CanFoldOffset(add ? offs : -offs, (int)size, true, out _))
if (InstEmitMemory.CanFoldOffset(context.MemoryManagerType, add ? offs : -offs, (int)size, true, out _))
{
InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, address.Operand, rnOperand);
InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, address.Operand, rnOperand);
if (!add)
{
@ -422,7 +422,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
else
{
InstEmitMemory.WriteAddShiftOffset(context.Arm64Assembler, address.Operand, rnOperand, InstEmitCommon.Const(offs), add, ArmShiftType.Lsl, 0);
InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, address.Operand, address.Operand);
InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, address.Operand, address.Operand);
offs = 0;
}
@ -473,7 +473,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
using ScopedRegister address = context.RegisterAllocator.AllocateTempGprRegisterScoped();
InstEmitMemory.WriteAddressTranslation(context.RegisterAllocator, context.Arm64Assembler, address.Operand, rnOperand);
InstEmitMemory.WriteAddressTranslation(context.MemoryManagerType, context.RegisterAllocator, context.Arm64Assembler, address.Operand, rnOperand);
callback(address.Operand);

View File

@ -350,11 +350,11 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
if (instInfo.AddressForm != AddressForm.None)
{
InstEmitMemory.RewriteInstruction(writer, regAlloc, instInfo.Name, instInfo.Flags, instInfo.AddressForm, pc, encoding);
InstEmitMemory.RewriteInstruction(memoryManager.Type, writer, regAlloc, instInfo.Name, instInfo.Flags, instInfo.AddressForm, pc, encoding);
}
else if (instInfo.Name == InstName.Sys)
{
InstEmitMemory.RewriteSysInstruction(writer, regAlloc, encoding);
InstEmitMemory.RewriteSysInstruction(memoryManager.Type, writer, regAlloc, encoding);
}
else if (instInfo.Name.IsSystem())
{

View File

@ -1,3 +1,4 @@
using ARMeilleure.Memory;
using Ryujinx.Cpu.LightningJit.CodeGen;
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
using System;
@ -10,7 +11,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
private const uint XMask = 0x3f808000u;
private const uint XValue = 0x8000000u;
public static void RewriteSysInstruction(CodeWriter writer, RegisterAllocator regAlloc, uint encoding)
public static void RewriteSysInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, uint encoding)
{
int rtIndex = RegisterUtils.ExtractRt(encoding);
if (rtIndex == RegisterUtils.ZrIndex)
@ -26,7 +27,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
Assembler asm = new(writer);
WriteAddressTranslation(regAlloc, ref asm, rt, guestAddress);
WriteAddressTranslation(mmType, regAlloc, ref asm, rt, guestAddress);
encoding = RegisterUtils.ReplaceRt(encoding, tempRegister);
@ -36,6 +37,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
}
public static void RewriteInstruction(
MemoryManagerType mmType,
CodeWriter writer,
RegisterAllocator regAlloc,
InstName name,
@ -47,19 +49,19 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
switch (addressForm)
{
case AddressForm.OffsetReg:
RewriteOffsetRegMemoryInstruction(writer, regAlloc, flags, encoding);
RewriteOffsetRegMemoryInstruction(mmType, writer, regAlloc, flags, encoding);
break;
case AddressForm.PostIndexed:
RewritePostIndexedMemoryInstruction(writer, regAlloc, flags, encoding);
RewritePostIndexedMemoryInstruction(mmType, writer, regAlloc, flags, encoding);
break;
case AddressForm.PreIndexed:
RewritePreIndexedMemoryInstruction(writer, regAlloc, flags, encoding);
RewritePreIndexedMemoryInstruction(mmType, writer, regAlloc, flags, encoding);
break;
case AddressForm.SignedScaled:
RewriteSignedScaledMemoryInstruction(writer, regAlloc, flags, encoding);
RewriteSignedScaledMemoryInstruction(mmType, writer, regAlloc, flags, encoding);
break;
case AddressForm.UnsignedScaled:
RewriteUnsignedScaledMemoryInstruction(writer, regAlloc, flags, encoding);
RewriteUnsignedScaledMemoryInstruction(mmType, writer, regAlloc, flags, encoding);
break;
case AddressForm.BaseRegister:
// Some applications uses unordered memory instructions in places where
@ -72,19 +74,19 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
encoding |= 1u << 15;
}
RewriteBaseRegisterMemoryInstruction(writer, regAlloc, encoding);
RewriteBaseRegisterMemoryInstruction(mmType, writer, regAlloc, encoding);
break;
case AddressForm.StructNoOffset:
RewriteBaseRegisterMemoryInstruction(writer, regAlloc, encoding);
RewriteBaseRegisterMemoryInstruction(mmType, writer, regAlloc, encoding);
break;
case AddressForm.BasePlusOffset:
RewriteBasePlusOffsetMemoryInstruction(writer, regAlloc, encoding);
RewriteBasePlusOffsetMemoryInstruction(mmType, writer, regAlloc, encoding);
break;
case AddressForm.Literal:
RewriteLiteralMemoryInstruction(writer, regAlloc, name, pc, encoding);
RewriteLiteralMemoryInstruction(mmType, writer, regAlloc, name, pc, encoding);
break;
case AddressForm.StructPostIndexedReg:
RewriteStructPostIndexedRegMemoryInstruction(writer, regAlloc, encoding);
RewriteStructPostIndexedRegMemoryInstruction(mmType, writer, regAlloc, encoding);
break;
default:
writer.WriteInstruction(encoding);
@ -92,7 +94,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
}
}
private static void RewriteOffsetRegMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding)
private static void RewriteOffsetRegMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding)
{
// TODO: Some unallocated encoding cases.
@ -116,7 +118,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
asm.Add(rn, guestAddress, guestOffset, extensionType, shift);
WriteAddressTranslation(regAlloc, ref asm, rn, rn);
WriteAddressTranslation(mmType, regAlloc, ref asm, rn, rn);
encoding = RegisterUtils.ReplaceRn(encoding, tempRegister);
encoding = (encoding & ~(0xfffu << 10)) | (1u << 24); // Register -> Unsigned offset
@ -126,7 +128,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
regAlloc.FreeTempGprRegister(tempRegister);
}
private static void RewritePostIndexedMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding)
private static void RewritePostIndexedMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding)
{
bool isPair = flags.HasFlag(InstFlags.Rt2);
int imm = isPair ? ExtractSImm7Scaled(flags, encoding) : ExtractSImm9(encoding);
@ -137,7 +139,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
Assembler asm = new(writer);
WriteAddressTranslation(regAlloc, ref asm, rn, guestAddress);
WriteAddressTranslation(mmType, regAlloc, ref asm, rn, guestAddress);
encoding = RegisterUtils.ReplaceRn(encoding, tempRegister);
@ -160,7 +162,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
regAlloc.FreeTempGprRegister(tempRegister);
}
private static void RewritePreIndexedMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding)
private static void RewritePreIndexedMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding)
{
bool isPair = flags.HasFlag(InstFlags.Rt2);
int imm = isPair ? ExtractSImm7Scaled(flags, encoding) : ExtractSImm9(encoding);
@ -172,7 +174,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
Assembler asm = new(writer);
WriteAddConstant(ref asm, guestAddress, guestAddress, imm);
WriteAddressTranslation(regAlloc, ref asm, rn, guestAddress);
WriteAddressTranslation(mmType, regAlloc, ref asm, rn, guestAddress);
encoding = RegisterUtils.ReplaceRn(encoding, tempRegister);
@ -193,27 +195,27 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
regAlloc.FreeTempGprRegister(tempRegister);
}
private static void RewriteSignedScaledMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding)
private static void RewriteSignedScaledMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding)
{
RewriteMemoryInstruction(writer, regAlloc, encoding, ExtractSImm7Scaled(flags, encoding), 0x7fu << 15);
RewriteMemoryInstruction(mmType, writer, regAlloc, encoding, ExtractSImm7Scaled(flags, encoding), 0x7fu << 15);
}
private static void RewriteUnsignedScaledMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding)
private static void RewriteUnsignedScaledMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, InstFlags flags, uint encoding)
{
RewriteMemoryInstruction(writer, regAlloc, encoding, ExtractUImm12Scaled(flags, encoding), 0xfffu << 10);
RewriteMemoryInstruction(mmType, writer, regAlloc, encoding, ExtractUImm12Scaled(flags, encoding), 0xfffu << 10);
}
private static void RewriteBaseRegisterMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, uint encoding)
private static void RewriteBaseRegisterMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, uint encoding)
{
RewriteMemoryInstruction(writer, regAlloc, encoding, 0, 0u);
RewriteMemoryInstruction(mmType, writer, regAlloc, encoding, 0, 0u);
}
private static void RewriteBasePlusOffsetMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, uint encoding)
private static void RewriteBasePlusOffsetMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, uint encoding)
{
RewriteMemoryInstruction(writer, regAlloc, encoding, ExtractSImm9(encoding), 0x1ffu << 12);
RewriteMemoryInstruction(mmType, writer, regAlloc, encoding, ExtractSImm9(encoding), 0x1ffu << 12);
}
private static void RewriteMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, uint encoding, int imm, uint immMask)
private static void RewriteMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, uint encoding, int imm, uint immMask)
{
int tempRegister = regAlloc.AllocateTempGprRegister();
Operand rn = new(tempRegister, RegisterType.Integer, OperandType.I64);
@ -221,13 +223,13 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
Assembler asm = new(writer);
bool canFoldOffset = CanFoldOffset(imm);
bool canFoldOffset = CanFoldOffset(mmType, imm);
if (canFoldOffset)
{
imm = 0;
}
WriteAddressTranslation(regAlloc, ref asm, rn, guestAddress, imm);
WriteAddressTranslation(mmType, regAlloc, ref asm, rn, guestAddress, imm);
encoding = RegisterUtils.ReplaceRn(encoding, tempRegister);
@ -241,7 +243,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
regAlloc.FreeTempGprRegister(tempRegister);
}
private static void RewriteLiteralMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, InstName name, ulong pc, uint encoding)
private static void RewriteLiteralMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, InstName name, ulong pc, uint encoding)
{
Assembler asm = new(writer);
@ -306,7 +308,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
int tempRegister = regAlloc.AllocateTempGprRegister();
Operand rn = new(tempRegister, RegisterType.Integer, OperandType.I64);
WriteAddressTranslation(regAlloc, ref asm, rn, targetAddress);
WriteAddressTranslation(mmType, regAlloc, ref asm, rn, targetAddress);
switch (name)
{
@ -330,7 +332,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
}
}
private static void RewriteStructPostIndexedRegMemoryInstruction(CodeWriter writer, RegisterAllocator regAlloc, uint encoding)
private static void RewriteStructPostIndexedRegMemoryInstruction(MemoryManagerType mmType, CodeWriter writer, RegisterAllocator regAlloc, uint encoding)
{
// TODO: Some unallocated encoding cases.
@ -342,7 +344,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
Assembler asm = new(writer);
WriteAddressTranslation(regAlloc, ref asm, rn, guestAddress);
WriteAddressTranslation(mmType, regAlloc, ref asm, rn, guestAddress);
encoding = RegisterUtils.ReplaceRn(encoding, tempRegister);
encoding &= ~((0x1fu << 16) | (1u << 23)); // Post-index -> No offset
@ -468,7 +470,13 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
regAlloc.FreeTempGprRegister(tempRegister);
}
private static void WriteAddressTranslation(RegisterAllocator regAlloc, ref Assembler asm, Operand destination, Operand guestAddress, int offset)
private static void WriteAddressTranslation(
MemoryManagerType mmType,
RegisterAllocator regAlloc,
ref Assembler asm,
Operand destination,
Operand guestAddress,
int offset)
{
if (offset != 0)
{
@ -490,17 +498,17 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
guestAddress = destination;
}
WriteAddressTranslation(regAlloc, ref asm, destination, guestAddress);
WriteAddressTranslation(mmType, regAlloc, ref asm, destination, guestAddress);
}
private static void WriteAddressTranslation(RegisterAllocator regAlloc, ref Assembler asm, Operand destination, ulong guestAddress)
private static void WriteAddressTranslation(MemoryManagerType mmType, RegisterAllocator regAlloc, ref Assembler asm, Operand destination, ulong guestAddress)
{
asm.Mov(destination, guestAddress);
WriteAddressTranslation(regAlloc, ref asm, destination, destination);
WriteAddressTranslation(mmType, regAlloc, ref asm, destination, destination);
}
private static void WriteAddressTranslation(RegisterAllocator regAlloc, ref Assembler asm, Operand destination, Operand guestAddress)
private static void WriteAddressTranslation(MemoryManagerType mmType, RegisterAllocator regAlloc, ref Assembler asm, Operand destination, Operand guestAddress)
{
Operand basePointer = new(regAlloc.FixedPageTableRegister, RegisterType.Integer, OperandType.I64);
@ -519,11 +527,9 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
}
}
private static bool CanFoldOffset(int offset)
private static bool CanFoldOffset(MemoryManagerType mmType, int offset)
{
// TODO: Check based on the memory manager mode.
return true;
return mmType == MemoryManagerType.HostMappedUnsafe;
}
private static int ExtractSImm7Scaled(InstFlags flags, uint encoding)