Implement inline memory load/store exclusive and ordered (#1413)

* Implement inline memory load/store exclusive

* Fix missing REX prefix on 8-bits CMPXCHG

* Increment PTC version due to bugfix

* Remove redundant memory checks

* Address PR feedback

* Increment PPTC version
This commit is contained in:
gdkchan 2020-07-30 11:29:28 -03:00 committed by GitHub
parent 57bb0abda3
commit 9878fc2d3c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 385 additions and 376 deletions

View file

@ -12,8 +12,9 @@ namespace ARMeilleure.Memory
void Write<T>(ulong va, T value) where T : unmanaged;
ref T GetRef<T>(ulong va) where T : unmanaged;
ref T GetRefNoChecks<T>(ulong va) where T : unmanaged;
bool IsMapped(ulong va);
void MarkRegionAsModified(ulong va, ulong size);
}
}

View file

@ -0,0 +1,23 @@
using System;
namespace ARMeilleure.Memory
{
class InvalidAccessException : Exception
{
public InvalidAccessException()
{
}
public InvalidAccessException(ulong address) : base($"Invalid memory access at virtual address 0x{address:X16}.")
{
}
public InvalidAccessException(string message) : base(message)
{
}
public InvalidAccessException(string message, Exception innerException) : base(message, innerException)
{
}
}
}

View file

@ -1,76 +0,0 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
namespace ARMeilleure.Memory
{
static class MemoryManagerPal
{
private delegate V128 CompareExchange128(ref V128 location, V128 expected, V128 desired);
private static CompareExchange128 _compareExchange128;
private static object _lock;
static MemoryManagerPal()
{
_lock = new object();
}
public static V128 AtomicLoad128(ref V128 location)
{
return GetCompareAndSwap128()(ref location, V128.Zero, V128.Zero);
}
public static V128 CompareAndSwap128(ref V128 location, V128 expected, V128 desired)
{
return GetCompareAndSwap128()(ref location, expected, desired);
}
private static CompareExchange128 GetCompareAndSwap128()
{
if (_compareExchange128 == null)
{
GenerateCompareAndSwap128();
}
return _compareExchange128;
}
private static void GenerateCompareAndSwap128()
{
lock (_lock)
{
if (_compareExchange128 != null)
{
return;
}
EmitterContext context = new EmitterContext();
Operand address = context.LoadArgument(OperandType.I64, 0);
Operand expected = context.LoadArgument(OperandType.V128, 1);
Operand desired = context.LoadArgument(OperandType.V128, 2);
Operand result = context.CompareAndSwap(address, expected, desired);
context.Return(result);
ControlFlowGraph cfg = context.GetControlFlowGraph();
OperandType[] argTypes = new OperandType[]
{
OperandType.I64,
OperandType.V128,
OperandType.V128
};
_compareExchange128 = Compiler.Compile<CompareExchange128>(
cfg,
argTypes,
OperandType.V128,
CompilerOptions.HighCq);
}
}
}
}