Move exclusive load to helper, reference call flag rather than literal 1.
This commit is contained in:
parent
589f11c2f7
commit
502cdf875c
5 changed files with 103 additions and 171 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
87
ARMeilleure/Instructions/InstEmitMemoryExHelper.cs
Normal file
87
ARMeilleure/Instructions/InstEmitMemoryExHelper.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue