Move exclusive load to helper, reference call flag rather than literal 1.

This commit is contained in:
riperiperi 2020-02-19 22:26:23 +00:00
parent 589f11c2f7
commit 502cdf875c
5 changed files with 103 additions and 171 deletions

View file

@ -3,6 +3,7 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using static ARMeilleure.Instructions.InstEmitFlowHelper;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -67,7 +68,7 @@ namespace ARMeilleure.Instructions
Operand addr = GetIntA32(context, op.Rm);
Operand bitOne = context.BitwiseAnd(addr, Const(1));
addr = context.BitwiseOr(addr, Const(1)); // Set call flag.
addr = context.BitwiseOr(addr, Const(CallFlag)); // Set call flag.
bool isThumb = IsThumb(context.CurrOp);

View file

@ -155,11 +155,11 @@ namespace ARMeilleure.Instructions
context.BranchIfTrue(lblArmMode, mode);
// Make this count as a call, the translator will ignore the low bit for the address.
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseOr(pc, Const(1))));
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseOr(pc, Const(InstEmitFlowHelper.CallFlag))));
context.MarkLabel(lblArmMode);
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseOr(context.BitwiseAnd(pc, Const(~3)), Const(1))));
context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseOr(context.BitwiseAnd(pc, Const(~3)), Const(InstEmitFlowHelper.CallFlag))));
}
public static Operand GetIntOrZR(ArmEmitterContext context, int regIndex)

View file

@ -5,6 +5,7 @@ using System;
using System.Diagnostics;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitMemoryExHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
namespace ARMeilleure.Instructions
@ -66,7 +67,7 @@ namespace ARMeilleure.Instructions
// method to read 128-bits atomically.
if (op.Size == 2)
{
Operand value = EmitLoad(context, address, exclusive, 3);
Operand value = EmitLoadExclusive(context, address, exclusive, 3);
Operand valueLow = context.ConvertI64ToI32(value);
@ -79,7 +80,7 @@ namespace ARMeilleure.Instructions
}
else if (op.Size == 3)
{
Operand value = EmitLoad(context, address, exclusive, 4);
Operand value = EmitLoadExclusive(context, address, exclusive, 4);
Operand valueLow = context.VectorExtract(OperandType.I64, value, 0);
Operand valueHigh = context.VectorExtract(OperandType.I64, value, 1);
@ -95,46 +96,11 @@ namespace ARMeilleure.Instructions
else
{
// 8, 16, 32 or 64-bits (non-pairwise) load.
Operand value = EmitLoad(context, address, exclusive, op.Size);
Operand value = EmitLoadExclusive(context, address, exclusive, op.Size);
SetIntOrZR(context, op.Rt, value);
}
}
private static Operand EmitLoad(
ArmEmitterContext context,
Operand address,
bool exclusive,
int size)
{
Delegate fallbackMethodDlg = null;
if (exclusive)
{
switch (size)
{
case 0: fallbackMethodDlg = new _U8_U64 (NativeInterface.ReadByteExclusive); break;
case 1: fallbackMethodDlg = new _U16_U64 (NativeInterface.ReadUInt16Exclusive); break;
case 2: fallbackMethodDlg = new _U32_U64 (NativeInterface.ReadUInt32Exclusive); break;
case 3: fallbackMethodDlg = new _U64_U64 (NativeInterface.ReadUInt64Exclusive); break;
case 4: fallbackMethodDlg = new _V128_U64(NativeInterface.ReadVector128Exclusive); break;
}
}
else
{
switch (size)
{
case 0: fallbackMethodDlg = new _U8_U64 (NativeInterface.ReadByte); break;
case 1: fallbackMethodDlg = new _U16_U64 (NativeInterface.ReadUInt16); break;
case 2: fallbackMethodDlg = new _U32_U64 (NativeInterface.ReadUInt32); break;
case 3: fallbackMethodDlg = new _U64_U64 (NativeInterface.ReadUInt64); break;
case 4: fallbackMethodDlg = new _V128_U64(NativeInterface.ReadVector128); break;
}
}
return context.Call(fallbackMethodDlg, address);
}
public static void Pfrm(ArmEmitterContext context)
{
// Memory Prefetch, execute as no-op.
@ -192,11 +158,11 @@ namespace ARMeilleure.Instructions
value = context.VectorInsert(value, t2, 1);
}
s = EmitStore(context, address, value, exclusive, op.Size + 1);
s = EmitStoreExclusive(context, address, value, exclusive, op.Size + 1);
}
else
{
s = EmitStore(context, address, t, exclusive, op.Size);
s = EmitStoreExclusive(context, address, t, exclusive, op.Size);
}
if (s != null)
@ -207,50 +173,6 @@ namespace ARMeilleure.Instructions
}
}
private static Operand EmitStore(
ArmEmitterContext context,
Operand address,
Operand value,
bool exclusive,
int size)
{
if (size < 3)
{
value = context.ConvertI64ToI32(value);
}
Delegate fallbackMethodDlg = null;
if (exclusive)
{
switch (size)
{
case 0: fallbackMethodDlg = new _S32_U64_U8 (NativeInterface.WriteByteExclusive); break;
case 1: fallbackMethodDlg = new _S32_U64_U16 (NativeInterface.WriteUInt16Exclusive); break;
case 2: fallbackMethodDlg = new _S32_U64_U32 (NativeInterface.WriteUInt32Exclusive); break;
case 3: fallbackMethodDlg = new _S32_U64_U64 (NativeInterface.WriteUInt64Exclusive); break;
case 4: fallbackMethodDlg = new _S32_U64_V128(NativeInterface.WriteVector128Exclusive); break;
}
return context.Call(fallbackMethodDlg, address, value);
}
else
{
switch (size)
{
case 0: fallbackMethodDlg = new _Void_U64_U8 (NativeInterface.WriteByte); break;
case 1: fallbackMethodDlg = new _Void_U64_U16 (NativeInterface.WriteUInt16); break;
case 2: fallbackMethodDlg = new _Void_U64_U32 (NativeInterface.WriteUInt32); break;
case 3: fallbackMethodDlg = new _Void_U64_U64 (NativeInterface.WriteUInt64); break;
case 4: fallbackMethodDlg = new _Void_U64_V128(NativeInterface.WriteVector128); break;
}
context.Call(fallbackMethodDlg, address, value);
return null;
}
}
private static void EmitBarrier(ArmEmitterContext context)
{
// Note: This barrier is most likely not necessary, and probably

View file

@ -2,9 +2,9 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitMemoryExHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
namespace ARMeilleure.Instructions
@ -153,7 +153,7 @@ namespace ARMeilleure.Instructions
// Keep loads atomic - make the call to get the whole region and then decompose it into parts
// for the registers.
Operand value = EmitExLoad(context, address, exclusive, size);
Operand value = EmitLoadExclusive(context, address, exclusive, size);
Operand valueLow = context.ConvertI64ToI32(value);
@ -180,7 +180,7 @@ namespace ARMeilleure.Instructions
}
else
{
SetIntA32(context, op.Rt, EmitExLoad(context, address, exclusive, size));
SetIntA32(context, op.Rt, EmitLoadExclusive(context, address, exclusive, size));
}
}
else
@ -198,7 +198,7 @@ namespace ARMeilleure.Instructions
context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
Operand leResult = context.BitwiseOr(lo, context.ShiftLeft(hi, Const(32)));
Operand leS = EmitExStore(context, address, leResult, exclusive, size);
Operand leS = EmitStoreExclusive(context, address, leResult, exclusive, size);
if (exclusive)
{
SetIntA32(context, op.Rd, leS);
@ -209,7 +209,7 @@ namespace ARMeilleure.Instructions
context.MarkLabel(lblBigEndian);
Operand beResult = context.BitwiseOr(hi, context.ShiftLeft(lo, Const(32)));
Operand beS = EmitExStore(context, address, beResult, exclusive, size);
Operand beS = EmitStoreExclusive(context, address, beResult, exclusive, size);
if (exclusive)
{
SetIntA32(context, op.Rd, beS);
@ -219,7 +219,7 @@ namespace ARMeilleure.Instructions
}
else
{
Operand s = EmitExStore(context, address, context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt)), exclusive, size);
Operand s = EmitStoreExclusive(context, address, context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt)), exclusive, size);
// This is only needed for exclusive stores. The function returns 0
// when the store is successful, and 1 otherwise.
if (exclusive)
@ -230,84 +230,6 @@ namespace ARMeilleure.Instructions
}
}
private static Operand EmitExLoad(
ArmEmitterContext context,
Operand address,
bool exclusive,
int size)
{
Delegate fallbackMethodDlg = null;
if (exclusive)
{
switch (size)
{
case 0: fallbackMethodDlg = new _U8_U64(NativeInterface.ReadByteExclusive); break;
case 1: fallbackMethodDlg = new _U16_U64(NativeInterface.ReadUInt16Exclusive); break;
case 2: fallbackMethodDlg = new _U32_U64(NativeInterface.ReadUInt32Exclusive); break;
case 3: fallbackMethodDlg = new _U64_U64(NativeInterface.ReadUInt64Exclusive); break;
case 4: fallbackMethodDlg = new _V128_U64(NativeInterface.ReadVector128Exclusive); break;
}
}
else
{
switch (size)
{
case 0: fallbackMethodDlg = new _U8_U64(NativeInterface.ReadByte); break;
case 1: fallbackMethodDlg = new _U16_U64(NativeInterface.ReadUInt16); break;
case 2: fallbackMethodDlg = new _U32_U64(NativeInterface.ReadUInt32); break;
case 3: fallbackMethodDlg = new _U64_U64(NativeInterface.ReadUInt64); break;
case 4: fallbackMethodDlg = new _V128_U64(NativeInterface.ReadVector128); break;
}
}
return context.Call(fallbackMethodDlg, address);
}
private static Operand EmitExStore(
ArmEmitterContext context,
Operand address,
Operand value,
bool exclusive,
int size)
{
if (size < 3)
{
value = context.ConvertI64ToI32(value);
}
Delegate fallbackMethodDlg = null;
if (exclusive)
{
switch (size)
{
case 0: fallbackMethodDlg = new _S32_U64_U8(NativeInterface.WriteByteExclusive); break;
case 1: fallbackMethodDlg = new _S32_U64_U16(NativeInterface.WriteUInt16Exclusive); break;
case 2: fallbackMethodDlg = new _S32_U64_U32(NativeInterface.WriteUInt32Exclusive); break;
case 3: fallbackMethodDlg = new _S32_U64_U64(NativeInterface.WriteUInt64Exclusive); break;
case 4: fallbackMethodDlg = new _S32_U64_V128(NativeInterface.WriteVector128Exclusive); break;
}
return context.Call(fallbackMethodDlg, address, value);
}
else
{
switch (size)
{
case 0: fallbackMethodDlg = new _Void_U64_U8(NativeInterface.WriteByte); break;
case 1: fallbackMethodDlg = new _Void_U64_U16(NativeInterface.WriteUInt16); break;
case 2: fallbackMethodDlg = new _Void_U64_U32(NativeInterface.WriteUInt32); break;
case 3: fallbackMethodDlg = new _Void_U64_U64(NativeInterface.WriteUInt64); break;
case 4: fallbackMethodDlg = new _Void_U64_V128(NativeInterface.WriteVector128); break;
}
context.Call(fallbackMethodDlg, address, value);
return null;
}
}
private static void EmitBarrier(ArmEmitterContext context)
{
// Note: This barrier is most likely not necessary, and probably

View file

@ -0,0 +1,87 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System;
namespace ARMeilleure.Instructions
{
static class InstEmitMemoryExHelper
{
public static Operand EmitLoadExclusive(
ArmEmitterContext context,
Operand address,
bool exclusive,
int size)
{
Delegate fallbackMethodDlg = null;
if (exclusive)
{
switch (size)
{
case 0: fallbackMethodDlg = new _U8_U64(NativeInterface.ReadByteExclusive); break;
case 1: fallbackMethodDlg = new _U16_U64(NativeInterface.ReadUInt16Exclusive); break;
case 2: fallbackMethodDlg = new _U32_U64(NativeInterface.ReadUInt32Exclusive); break;
case 3: fallbackMethodDlg = new _U64_U64(NativeInterface.ReadUInt64Exclusive); break;
case 4: fallbackMethodDlg = new _V128_U64(NativeInterface.ReadVector128Exclusive); break;
}
}
else
{
switch (size)
{
case 0: fallbackMethodDlg = new _U8_U64(NativeInterface.ReadByte); break;
case 1: fallbackMethodDlg = new _U16_U64(NativeInterface.ReadUInt16); break;
case 2: fallbackMethodDlg = new _U32_U64(NativeInterface.ReadUInt32); break;
case 3: fallbackMethodDlg = new _U64_U64(NativeInterface.ReadUInt64); break;
case 4: fallbackMethodDlg = new _V128_U64(NativeInterface.ReadVector128); break;
}
}
return context.Call(fallbackMethodDlg, address);
}
public static Operand EmitStoreExclusive(
ArmEmitterContext context,
Operand address,
Operand value,
bool exclusive,
int size)
{
if (size < 3)
{
value = context.ConvertI64ToI32(value);
}
Delegate fallbackMethodDlg = null;
if (exclusive)
{
switch (size)
{
case 0: fallbackMethodDlg = new _S32_U64_U8(NativeInterface.WriteByteExclusive); break;
case 1: fallbackMethodDlg = new _S32_U64_U16(NativeInterface.WriteUInt16Exclusive); break;
case 2: fallbackMethodDlg = new _S32_U64_U32(NativeInterface.WriteUInt32Exclusive); break;
case 3: fallbackMethodDlg = new _S32_U64_U64(NativeInterface.WriteUInt64Exclusive); break;
case 4: fallbackMethodDlg = new _S32_U64_V128(NativeInterface.WriteVector128Exclusive); break;
}
return context.Call(fallbackMethodDlg, address, value);
}
else
{
switch (size)
{
case 0: fallbackMethodDlg = new _Void_U64_U8(NativeInterface.WriteByte); break;
case 1: fallbackMethodDlg = new _Void_U64_U16(NativeInterface.WriteUInt16); break;
case 2: fallbackMethodDlg = new _Void_U64_U32(NativeInterface.WriteUInt32); break;
case 3: fallbackMethodDlg = new _Void_U64_U64(NativeInterface.WriteUInt64); break;
case 4: fallbackMethodDlg = new _Void_U64_V128(NativeInterface.WriteVector128); break;
}
context.Call(fallbackMethodDlg, address, value);
return null;
}
}
}
}