mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-07-23 13:07:10 +02:00
[ARMeilleure] Address dotnet-format issues (#5357)
* dotnet format style --severity info Some changes were manually reverted. * dotnet format analyzers --serverity info Some changes have been minimally adapted. * Restore a few unused methods and variables * Silence dotnet format IDE0060 warnings * Silence dotnet format IDE0052 warnings * Address or silence dotnet format IDE1006 warnings * Address or silence dotnet format CA2208 warnings * Address dotnet format CA1822 warnings * Address or silence dotnet format CA1069 warnings * Silence CA1806 and CA1834 issues * Address dotnet format CA1401 warnings * Fix new dotnet-format issues after rebase * Address review comments * Address dotnet format CA2208 warnings properly * Fix formatting for switch expressions * Address most dotnet format whitespace warnings * Apply dotnet format whitespace formatting A few of them have been manually reverted and the corresponding warning was silenced * Add previously silenced warnings back I have no clue how these disappeared * Revert formatting changes for OpCodeTable.cs * Enable formatting for a few cases again * Format if-blocks correctly * Enable formatting for a few more cases again * Fix inline comment alignment * Run dotnet format after rebase and remove unused usings - analyzers - style - whitespace * Disable 'prefer switch expression' rule * Add comments to disabled warnings * Remove a few unused parameters * Adjust namespaces * Simplify properties and array initialization, Use const when possible, Remove trailing commas * Start working on disabled warnings * Fix and silence a few dotnet-format warnings again * Address IDE0251 warnings * Address a few disabled IDE0060 warnings * Silence IDE0060 in .editorconfig * Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas" This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e. * dotnet format whitespace after rebase * First dotnet format pass * Remove unnecessary formatting exclusion * Add unsafe dotnet format changes * Change visibility of JitSupportDarwin to internal
This commit is contained in:
parent
2de78a2d55
commit
ff53dcf560
300 changed files with 3515 additions and 3120 deletions
|
@ -7,7 +7,8 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
static class CryptoHelper
|
||||
{
|
||||
#region "LookUp Tables"
|
||||
#region "LookUp Tables"
|
||||
#pragma warning disable IDE1006 // Naming rule violation
|
||||
private static ReadOnlySpan<byte> _sBox => new byte[]
|
||||
{
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
|
@ -25,7 +26,7 @@ namespace ARMeilleure.Instructions
|
|||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _invSBox => new byte[]
|
||||
|
@ -45,7 +46,7 @@ namespace ARMeilleure.Instructions
|
|||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul02 => new byte[]
|
||||
|
@ -65,7 +66,7 @@ namespace ARMeilleure.Instructions
|
|||
0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
|
||||
0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
|
||||
0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
|
||||
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
|
||||
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul03 => new byte[]
|
||||
|
@ -85,7 +86,7 @@ namespace ARMeilleure.Instructions
|
|||
0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
|
||||
0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
|
||||
0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
|
||||
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
|
||||
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul09 => new byte[]
|
||||
|
@ -105,7 +106,7 @@ namespace ARMeilleure.Instructions
|
|||
0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
|
||||
0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
|
||||
0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
|
||||
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46
|
||||
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul0B => new byte[]
|
||||
|
@ -125,7 +126,7 @@ namespace ARMeilleure.Instructions
|
|||
0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
|
||||
0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
|
||||
0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
|
||||
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3
|
||||
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul0D => new byte[]
|
||||
|
@ -145,7 +146,7 @@ namespace ARMeilleure.Instructions
|
|||
0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
|
||||
0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
|
||||
0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
|
||||
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97
|
||||
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul0E => new byte[]
|
||||
|
@ -165,23 +166,24 @@ namespace ARMeilleure.Instructions
|
|||
0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
|
||||
0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
|
||||
0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
|
||||
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d
|
||||
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _srPerm => new byte[]
|
||||
{
|
||||
0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3
|
||||
0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _isrPerm => new byte[]
|
||||
{
|
||||
0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11
|
||||
0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11,
|
||||
};
|
||||
#endregion
|
||||
#pragma warning restore IDE1006
|
||||
#endregion
|
||||
|
||||
public static V128 AesInvMixColumns(V128 op)
|
||||
{
|
||||
byte[] inState = op.ToArray();
|
||||
byte[] inState = op.ToArray();
|
||||
byte[] outState = new byte[16];
|
||||
|
||||
for (int columns = 0; columns <= 3; columns++)
|
||||
|
@ -204,7 +206,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static V128 AesInvShiftRows(V128 op)
|
||||
{
|
||||
byte[] inState = op.ToArray();
|
||||
byte[] inState = op.ToArray();
|
||||
byte[] outState = new byte[16];
|
||||
|
||||
for (int idx = 0; idx <= 15; idx++)
|
||||
|
@ -217,7 +219,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static V128 AesInvSubBytes(V128 op)
|
||||
{
|
||||
byte[] inState = op.ToArray();
|
||||
byte[] inState = op.ToArray();
|
||||
byte[] outState = new byte[16];
|
||||
|
||||
for (int idx = 0; idx <= 15; idx++)
|
||||
|
@ -230,7 +232,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static V128 AesMixColumns(V128 op)
|
||||
{
|
||||
byte[] inState = op.ToArray();
|
||||
byte[] inState = op.ToArray();
|
||||
byte[] outState = new byte[16];
|
||||
|
||||
for (int columns = 0; columns <= 3; columns++)
|
||||
|
@ -253,7 +255,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static V128 AesShiftRows(V128 op)
|
||||
{
|
||||
byte[] inState = op.ToArray();
|
||||
byte[] inState = op.ToArray();
|
||||
byte[] outState = new byte[16];
|
||||
|
||||
for (int idx = 0; idx <= 15; idx++)
|
||||
|
@ -266,7 +268,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static V128 AesSubBytes(V128 op)
|
||||
{
|
||||
byte[] inState = op.ToArray();
|
||||
byte[] inState = op.ToArray();
|
||||
byte[] outState = new byte[16];
|
||||
|
||||
for (int idx = 0; idx <= 15; idx++)
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitAluHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -12,7 +11,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
static partial class InstEmit
|
||||
{
|
||||
public static void Adc(ArmEmitterContext context) => EmitAdc(context, setFlags: false);
|
||||
public static void Adc(ArmEmitterContext context) => EmitAdc(context, setFlags: false);
|
||||
public static void Adcs(ArmEmitterContext context) => EmitAdc(context, setFlags: true);
|
||||
|
||||
private static void EmitAdc(ArmEmitterContext context, bool setFlags)
|
||||
|
@ -87,7 +86,7 @@ namespace ARMeilleure.Instructions
|
|||
SetAluDOrZR(context, context.ShiftRightSI(GetAluN(context), GetAluMShift(context)));
|
||||
}
|
||||
|
||||
public static void Bic(ArmEmitterContext context) => EmitBic(context, setFlags: false);
|
||||
public static void Bic(ArmEmitterContext context) => EmitBic(context, setFlags: false);
|
||||
public static void Bics(ArmEmitterContext context) => EmitBic(context, setFlags: true);
|
||||
|
||||
private static void EmitBic(ArmEmitterContext context, bool setFlags)
|
||||
|
@ -190,7 +189,7 @@ namespace ARMeilleure.Instructions
|
|||
SetAluDOrZR(context, context.ShiftRightUI(GetAluN(context), GetAluMShift(context)));
|
||||
}
|
||||
|
||||
public static void Sbc(ArmEmitterContext context) => EmitSbc(context, setFlags: false);
|
||||
public static void Sbc(ArmEmitterContext context) => EmitSbc(context, setFlags: false);
|
||||
public static void Sbcs(ArmEmitterContext context) => EmitSbc(context, setFlags: true);
|
||||
|
||||
private static void EmitSbc(ArmEmitterContext context, bool setFlags)
|
||||
|
@ -281,16 +280,16 @@ namespace ARMeilleure.Instructions
|
|||
Debug.Assert(op.Type == OperandType.I64);
|
||||
|
||||
Operand val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xaaaaaaaaaaaaaaaaul)), Const(1)),
|
||||
context.ShiftLeft (context.BitwiseAnd(op, Const(0x5555555555555555ul)), Const(1)));
|
||||
context.ShiftLeft(context.BitwiseAnd(op, Const(0x5555555555555555ul)), Const(1)));
|
||||
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xccccccccccccccccul)), Const(2)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x3333333333333333ul)), Const(2)));
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x3333333333333333ul)), Const(2)));
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xf0f0f0f0f0f0f0f0ul)), Const(4)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x0f0f0f0f0f0f0f0ful)), Const(4)));
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x0f0f0f0f0f0f0f0ful)), Const(4)));
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xff00ff00ff00ff00ul)), Const(8)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x00ff00ff00ff00fful)), Const(8)));
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x00ff00ff00ff00fful)), Const(8)));
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xffff0000ffff0000ul)), Const(16)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x0000ffff0000fffful)), Const(16)));
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x0000ffff0000fffful)), Const(16)));
|
||||
|
||||
return context.BitwiseOr(context.ShiftRightUI(val, Const(32)), context.ShiftLeft(val, Const(32)));
|
||||
}
|
||||
|
@ -340,7 +339,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand val = EmitReverseBytes16_64Op(context, op);
|
||||
|
||||
return context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xffff0000ffff0000ul)), Const(16)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x0000ffff0000fffful)), Const(16)));
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x0000ffff0000fffful)), Const(16)));
|
||||
}
|
||||
|
||||
public static void Rev64(ArmEmitterContext context)
|
||||
|
|
|
@ -2,13 +2,14 @@ using ARMeilleure.Decoders;
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using static ARMeilleure.Instructions.InstEmitAluHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
[SuppressMessage("Style", "IDE0059: Remove unnecessary value assignment")]
|
||||
static partial class InstEmit32
|
||||
{
|
||||
public static void Add(ArmEmitterContext context)
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void EmitNZFlagsCheck(ArmEmitterContext context, Operand d)
|
||||
{
|
||||
SetFlag(context, PState.NFlag, context.ICompareLess (d, Const(d.Type, 0)));
|
||||
SetFlag(context, PState.NFlag, context.ICompareLess(d, Const(d.Type, 0)));
|
||||
SetFlag(context, PState.ZFlag, context.ICompareEqual(d, Const(d.Type, 0)));
|
||||
}
|
||||
|
||||
|
@ -196,60 +196,73 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
// ARM32.
|
||||
case IOpCode32AluImm op:
|
||||
{
|
||||
if (ShouldSetFlags(context) && op.IsRotated && setCarry)
|
||||
{
|
||||
SetFlag(context, PState.CFlag, Const((uint)op.Immediate >> 31));
|
||||
if (ShouldSetFlags(context) && op.IsRotated && setCarry)
|
||||
{
|
||||
SetFlag(context, PState.CFlag, Const((uint)op.Immediate >> 31));
|
||||
}
|
||||
|
||||
return Const(op.Immediate);
|
||||
}
|
||||
|
||||
case IOpCode32AluImm16 op:
|
||||
return Const(op.Immediate);
|
||||
}
|
||||
|
||||
case IOpCode32AluImm16 op: return Const(op.Immediate);
|
||||
case IOpCode32AluRsImm op:
|
||||
return GetMShiftedByImmediate(context, op, setCarry);
|
||||
case IOpCode32AluRsReg op:
|
||||
return GetMShiftedByReg(context, op, setCarry);
|
||||
|
||||
case IOpCode32AluRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
|
||||
case IOpCode32AluRsReg op: return GetMShiftedByReg(context, op, setCarry);
|
||||
|
||||
case IOpCode32AluReg op: return GetIntA32(context, op.Rm);
|
||||
case IOpCode32AluReg op:
|
||||
return GetIntA32(context, op.Rm);
|
||||
|
||||
// ARM64.
|
||||
case IOpCodeAluImm op:
|
||||
{
|
||||
if (op.GetOperandType() == OperandType.I32)
|
||||
{
|
||||
return Const((int)op.Immediate);
|
||||
if (op.GetOperandType() == OperandType.I32)
|
||||
{
|
||||
return Const((int)op.Immediate);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Const(op.Immediate);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return Const(op.Immediate);
|
||||
}
|
||||
}
|
||||
|
||||
case IOpCodeAluRs op:
|
||||
{
|
||||
Operand value = GetIntOrZR(context, op.Rm);
|
||||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsl: value = context.ShiftLeft (value, Const(op.Shift)); break;
|
||||
case ShiftType.Lsr: value = context.ShiftRightUI(value, Const(op.Shift)); break;
|
||||
case ShiftType.Asr: value = context.ShiftRightSI(value, Const(op.Shift)); break;
|
||||
case ShiftType.Ror: value = context.RotateRight (value, Const(op.Shift)); break;
|
||||
Operand value = GetIntOrZR(context, op.Rm);
|
||||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsl:
|
||||
value = context.ShiftLeft(value, Const(op.Shift));
|
||||
break;
|
||||
case ShiftType.Lsr:
|
||||
value = context.ShiftRightUI(value, Const(op.Shift));
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
value = context.ShiftRightSI(value, Const(op.Shift));
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
value = context.RotateRight(value, Const(op.Shift));
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
case IOpCodeAluRx op:
|
||||
{
|
||||
Operand value = GetExtendedM(context, op.Rm, op.IntType);
|
||||
{
|
||||
Operand value = GetExtendedM(context, op.Rm, op.IntType);
|
||||
|
||||
value = context.ShiftLeft(value, Const(op.Shift));
|
||||
value = context.ShiftLeft(value, Const(op.Shift));
|
||||
|
||||
return value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
default: throw InvalidOpCodeType(context.CurrOp);
|
||||
default:
|
||||
throw InvalidOpCodeType(context.CurrOp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,9 +282,15 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsr: shift = 32; break;
|
||||
case ShiftType.Asr: shift = 32; break;
|
||||
case ShiftType.Ror: shift = 1; break;
|
||||
case ShiftType.Lsr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
shift = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,9 +300,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsl: m = GetLslC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Lsr: m = GetLsrC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Asr: m = GetAsrC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Lsl:
|
||||
m = GetLslC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Lsr:
|
||||
m = GetLsrC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
m = GetAsrC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
if (op.Immediate != 0)
|
||||
{
|
||||
|
@ -306,9 +331,15 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (shiftType)
|
||||
{
|
||||
case ShiftType.Lsr: shift = 32; break;
|
||||
case ShiftType.Asr: shift = 32; break;
|
||||
case ShiftType.Ror: shift = 1; break;
|
||||
case ShiftType.Lsr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
shift = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,10 +359,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsl: shiftResult = EmitLslC(context, m, setCarry, s, shiftIsZero); break;
|
||||
case ShiftType.Lsr: shiftResult = EmitLsrC(context, m, setCarry, s, shiftIsZero); break;
|
||||
case ShiftType.Asr: shiftResult = EmitAsrC(context, m, setCarry, s, shiftIsZero); break;
|
||||
case ShiftType.Ror: shiftResult = EmitRorC(context, m, setCarry, s, shiftIsZero); break;
|
||||
case ShiftType.Lsl:
|
||||
shiftResult = EmitLslC(context, m, setCarry, s, shiftIsZero);
|
||||
break;
|
||||
case ShiftType.Lsr:
|
||||
shiftResult = EmitLsrC(context, m, setCarry, s, shiftIsZero);
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shiftResult = EmitAsrC(context, m, setCarry, s, shiftIsZero);
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
shiftResult = EmitRorC(context, m, setCarry, s, shiftIsZero);
|
||||
break;
|
||||
}
|
||||
|
||||
return context.ConditionalSelect(shiftIsZero, zeroResult, shiftResult);
|
||||
|
|
|
@ -84,9 +84,9 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
res = context.ShiftLeft (res, Const(bitsCount - 1 - op.Pos));
|
||||
res = context.ShiftLeft(res, Const(bitsCount - 1 - op.Pos));
|
||||
res = context.ShiftRightSI(res, Const(bitsCount - 1));
|
||||
res = context.BitwiseAnd (res, Const(res.Type, ~op.TMask));
|
||||
res = context.BitwiseAnd(res, Const(res.Type, ~op.TMask));
|
||||
|
||||
Operand n2 = GetBfmN(context);
|
||||
|
||||
|
@ -193,4 +193,4 @@ namespace ARMeilleure.Instructions
|
|||
return context.BitwiseAnd(context.RotateRight(res, Const(op.Shift)), Const(res.Type, mask));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ using ARMeilleure.Decoders;
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitAluHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
|
@ -20,7 +19,7 @@ namespace ARMeilleure.Instructions
|
|||
OpCodeCcmp op = (OpCodeCcmp)context.CurrOp;
|
||||
|
||||
Operand lblTrue = Label();
|
||||
Operand lblEnd = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
||||
EmitCondBranch(context, lblTrue, op.Cond);
|
||||
|
||||
|
@ -58,4 +57,4 @@ namespace ARMeilleure.Instructions
|
|||
context.MarkLabel(lblEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -15,10 +14,10 @@ namespace ARMeilleure.Instructions
|
|||
None,
|
||||
Increment,
|
||||
Invert,
|
||||
Negate
|
||||
Negate,
|
||||
}
|
||||
|
||||
public static void Csel(ArmEmitterContext context) => EmitCsel(context, CselOperation.None);
|
||||
public static void Csel(ArmEmitterContext context) => EmitCsel(context, CselOperation.None);
|
||||
public static void Csinc(ArmEmitterContext context) => EmitCsel(context, CselOperation.Increment);
|
||||
public static void Csinv(ArmEmitterContext context) => EmitCsel(context, CselOperation.Invert);
|
||||
public static void Csneg(ArmEmitterContext context) => EmitCsel(context, CselOperation.Negate);
|
||||
|
@ -50,4 +49,4 @@ namespace ARMeilleure.Instructions
|
|||
SetIntOrZR(context, op.Rd, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -23,7 +22,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand divisorIsZero = context.ICompareEqual(m, Const(m.Type, 0));
|
||||
|
||||
Operand lblBadDiv = Label();
|
||||
Operand lblEnd = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
||||
context.BranchIfTrue(lblBadDiv, divisorIsZero);
|
||||
|
||||
|
@ -33,7 +32,7 @@ namespace ARMeilleure.Instructions
|
|||
bool is32Bits = op.RegisterSize == RegisterSize.Int32;
|
||||
|
||||
Operand intMin = is32Bits ? Const(int.MinValue) : Const(long.MinValue);
|
||||
Operand minus1 = is32Bits ? Const(-1) : Const(-1L);
|
||||
Operand minus1 = is32Bits ? Const(-1) : Const(-1L);
|
||||
|
||||
Operand nIsIntMin = context.ICompareEqual(n, intMin);
|
||||
Operand mIsMinus1 = context.ICompareEqual(m, minus1);
|
||||
|
@ -51,7 +50,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand d = unsigned
|
||||
? context.DivideUI(n, m)
|
||||
: context.Divide (n, m);
|
||||
: context.Divide(n, m);
|
||||
|
||||
SetAluDOrZR(context, d);
|
||||
|
||||
|
|
|
@ -52,4 +52,4 @@ namespace ARMeilleure.Instructions
|
|||
context.Return(Const(op.Address));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
public static void Cbnz(ArmEmitterContext context) => EmitCb(context, onNotZero: true);
|
||||
public static void Cbz(ArmEmitterContext context) => EmitCb(context, onNotZero: false);
|
||||
public static void Cbz(ArmEmitterContext context) => EmitCb(context, onNotZero: false);
|
||||
|
||||
private static void EmitCb(ArmEmitterContext context, bool onNotZero)
|
||||
{
|
||||
|
@ -70,7 +70,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
public static void Tbnz(ArmEmitterContext context) => EmitTb(context, onNotZero: true);
|
||||
public static void Tbz(ArmEmitterContext context) => EmitTb(context, onNotZero: false);
|
||||
public static void Tbz(ArmEmitterContext context) => EmitTb(context, onNotZero: false);
|
||||
|
||||
private static void EmitTb(ArmEmitterContext context, bool onNotZero)
|
||||
{
|
||||
|
@ -104,4 +104,4 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
public static void Cbnz(ArmEmitterContext context) => EmitCb(context, onNotZero: true);
|
||||
public static void Cbz(ArmEmitterContext context) => EmitCb(context, onNotZero: false);
|
||||
public static void Cbz(ArmEmitterContext context) => EmitCb(context, onNotZero: false);
|
||||
|
||||
private static void EmitCb(ArmEmitterContext context, bool onNotZero)
|
||||
{
|
||||
|
@ -109,7 +109,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
public static void Tbb(ArmEmitterContext context) => EmitTb(context, halfword: false);
|
||||
public static void Tbh(ArmEmitterContext context) => EmitTb(context, halfword: true);
|
||||
public static void Tbh(ArmEmitterContext context) => EmitTb(context, halfword: true);
|
||||
|
||||
private static void EmitTb(ArmEmitterContext context, bool halfword)
|
||||
{
|
||||
|
@ -133,4 +133,4 @@ namespace ARMeilleure.Instructions
|
|||
EmitVirtualJump(context, targetAddress, isReturn: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,66 +75,66 @@ namespace ARMeilleure.Instructions
|
|||
break;
|
||||
|
||||
case Condition.GtUn:
|
||||
{
|
||||
Operand c = GetFlag(PState.CFlag);
|
||||
Operand z = GetFlag(PState.ZFlag);
|
||||
{
|
||||
Operand c = GetFlag(PState.CFlag);
|
||||
Operand z = GetFlag(PState.ZFlag);
|
||||
|
||||
value = context.BitwiseAnd(c, Inverse(z));
|
||||
value = context.BitwiseAnd(c, Inverse(z));
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Condition.LeUn:
|
||||
{
|
||||
Operand c = GetFlag(PState.CFlag);
|
||||
Operand z = GetFlag(PState.ZFlag);
|
||||
{
|
||||
Operand c = GetFlag(PState.CFlag);
|
||||
Operand z = GetFlag(PState.ZFlag);
|
||||
|
||||
value = context.BitwiseOr(Inverse(c), z);
|
||||
value = context.BitwiseOr(Inverse(c), z);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Condition.Ge:
|
||||
{
|
||||
Operand n = GetFlag(PState.NFlag);
|
||||
Operand v = GetFlag(PState.VFlag);
|
||||
{
|
||||
Operand n = GetFlag(PState.NFlag);
|
||||
Operand v = GetFlag(PState.VFlag);
|
||||
|
||||
value = context.ICompareEqual(n, v);
|
||||
value = context.ICompareEqual(n, v);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Condition.Lt:
|
||||
{
|
||||
Operand n = GetFlag(PState.NFlag);
|
||||
Operand v = GetFlag(PState.VFlag);
|
||||
{
|
||||
Operand n = GetFlag(PState.NFlag);
|
||||
Operand v = GetFlag(PState.VFlag);
|
||||
|
||||
value = context.ICompareNotEqual(n, v);
|
||||
value = context.ICompareNotEqual(n, v);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Condition.Gt:
|
||||
{
|
||||
Operand n = GetFlag(PState.NFlag);
|
||||
Operand z = GetFlag(PState.ZFlag);
|
||||
Operand v = GetFlag(PState.VFlag);
|
||||
{
|
||||
Operand n = GetFlag(PState.NFlag);
|
||||
Operand z = GetFlag(PState.ZFlag);
|
||||
Operand v = GetFlag(PState.VFlag);
|
||||
|
||||
value = context.BitwiseAnd(Inverse(z), context.ICompareEqual(n, v));
|
||||
value = context.BitwiseAnd(Inverse(z), context.ICompareEqual(n, v));
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Condition.Le:
|
||||
{
|
||||
Operand n = GetFlag(PState.NFlag);
|
||||
Operand z = GetFlag(PState.ZFlag);
|
||||
Operand v = GetFlag(PState.VFlag);
|
||||
{
|
||||
Operand n = GetFlag(PState.NFlag);
|
||||
Operand z = GetFlag(PState.ZFlag);
|
||||
Operand v = GetFlag(PState.VFlag);
|
||||
|
||||
value = context.BitwiseOr(z, context.ICompareNotEqual(n, v));
|
||||
value = context.BitwiseOr(z, context.ICompareNotEqual(n, v));
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
string name = (size, castagnoli) switch
|
||||
string name = (size, castagnoli) switch
|
||||
{
|
||||
(0, false) => nameof(SoftFallback.Crc32b),
|
||||
(1, false) => nameof(SoftFallback.Crc32h),
|
||||
|
@ -55,7 +55,7 @@ namespace ARMeilleure.Instructions
|
|||
(1, true) => nameof(SoftFallback.Crc32ch),
|
||||
(2, true) => nameof(SoftFallback.Crc32cw),
|
||||
(3, true) => nameof(SoftFallback.Crc32cx),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(size))
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(size)),
|
||||
};
|
||||
|
||||
return context.Call(typeof(SoftFallback).GetMethod(name), crc, value);
|
||||
|
@ -71,9 +71,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: data = context.VectorInsert8(context.VectorZero(), data, 0); break;
|
||||
case 1: data = context.VectorInsert16(context.VectorZero(), data, 0); break;
|
||||
case 2: data = context.VectorInsert(context.VectorZero(), data, 0); break;
|
||||
case 0:
|
||||
data = context.VectorInsert8(context.VectorZero(), data, 0);
|
||||
break;
|
||||
case 1:
|
||||
data = context.VectorInsert16(context.VectorZero(), data, 0);
|
||||
break;
|
||||
case 2:
|
||||
data = context.VectorInsert(context.VectorZero(), data, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
int bitsize = 8 << size;
|
||||
|
|
|
@ -16,13 +16,25 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (type)
|
||||
{
|
||||
case IntType.UInt8: value = context.ZeroExtend8 (value.Type, value); break;
|
||||
case IntType.UInt16: value = context.ZeroExtend16(value.Type, value); break;
|
||||
case IntType.UInt32: value = context.ZeroExtend32(value.Type, value); break;
|
||||
case IntType.UInt8:
|
||||
value = context.ZeroExtend8(value.Type, value);
|
||||
break;
|
||||
case IntType.UInt16:
|
||||
value = context.ZeroExtend16(value.Type, value);
|
||||
break;
|
||||
case IntType.UInt32:
|
||||
value = context.ZeroExtend32(value.Type, value);
|
||||
break;
|
||||
|
||||
case IntType.Int8: value = context.SignExtend8 (value.Type, value); break;
|
||||
case IntType.Int16: value = context.SignExtend16(value.Type, value); break;
|
||||
case IntType.Int32: value = context.SignExtend32(value.Type, value); break;
|
||||
case IntType.Int8:
|
||||
value = context.SignExtend8(value.Type, value);
|
||||
break;
|
||||
case IntType.Int16:
|
||||
value = context.SignExtend16(value.Type, value);
|
||||
break;
|
||||
case IntType.Int32:
|
||||
value = context.SignExtend32(value.Type, value);
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
@ -100,78 +112,51 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static int GetBankedRegisterAlias(Aarch32Mode mode, int regIndex)
|
||||
{
|
||||
switch (regIndex)
|
||||
return regIndex switch
|
||||
{
|
||||
case 8: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R8Fiq
|
||||
: RegisterAlias.R8Usr;
|
||||
|
||||
case 9: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R9Fiq
|
||||
: RegisterAlias.R9Usr;
|
||||
|
||||
case 10: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R10Fiq
|
||||
: RegisterAlias.R10Usr;
|
||||
|
||||
case 11: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R11Fiq
|
||||
: RegisterAlias.R11Usr;
|
||||
|
||||
case 12: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R12Fiq
|
||||
: RegisterAlias.R12Usr;
|
||||
|
||||
case 13:
|
||||
switch (mode)
|
||||
{
|
||||
case Aarch32Mode.User:
|
||||
case Aarch32Mode.System: return RegisterAlias.SpUsr;
|
||||
case Aarch32Mode.Fiq: return RegisterAlias.SpFiq;
|
||||
case Aarch32Mode.Irq: return RegisterAlias.SpIrq;
|
||||
case Aarch32Mode.Supervisor: return RegisterAlias.SpSvc;
|
||||
case Aarch32Mode.Abort: return RegisterAlias.SpAbt;
|
||||
case Aarch32Mode.Hypervisor: return RegisterAlias.SpHyp;
|
||||
case Aarch32Mode.Undefined: return RegisterAlias.SpUnd;
|
||||
|
||||
default: throw new ArgumentException(nameof(mode));
|
||||
}
|
||||
|
||||
case 14:
|
||||
switch (mode)
|
||||
{
|
||||
case Aarch32Mode.User:
|
||||
case Aarch32Mode.Hypervisor:
|
||||
case Aarch32Mode.System: return RegisterAlias.LrUsr;
|
||||
case Aarch32Mode.Fiq: return RegisterAlias.LrFiq;
|
||||
case Aarch32Mode.Irq: return RegisterAlias.LrIrq;
|
||||
case Aarch32Mode.Supervisor: return RegisterAlias.LrSvc;
|
||||
case Aarch32Mode.Abort: return RegisterAlias.LrAbt;
|
||||
case Aarch32Mode.Undefined: return RegisterAlias.LrUnd;
|
||||
|
||||
default: throw new ArgumentException(nameof(mode));
|
||||
}
|
||||
|
||||
default: throw new ArgumentOutOfRangeException(nameof(regIndex));
|
||||
}
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
8 => mode == Aarch32Mode.Fiq ? RegisterAlias.R8Fiq : RegisterAlias.R8Usr,
|
||||
9 => mode == Aarch32Mode.Fiq ? RegisterAlias.R9Fiq : RegisterAlias.R9Usr,
|
||||
10 => mode == Aarch32Mode.Fiq ? RegisterAlias.R10Fiq : RegisterAlias.R10Usr,
|
||||
11 => mode == Aarch32Mode.Fiq ? RegisterAlias.R11Fiq : RegisterAlias.R11Usr,
|
||||
12 => mode == Aarch32Mode.Fiq ? RegisterAlias.R12Fiq : RegisterAlias.R12Usr,
|
||||
13 => mode switch
|
||||
{
|
||||
Aarch32Mode.User or Aarch32Mode.System => RegisterAlias.SpUsr,
|
||||
Aarch32Mode.Fiq => RegisterAlias.SpFiq,
|
||||
Aarch32Mode.Irq => RegisterAlias.SpIrq,
|
||||
Aarch32Mode.Supervisor => RegisterAlias.SpSvc,
|
||||
Aarch32Mode.Abort => RegisterAlias.SpAbt,
|
||||
Aarch32Mode.Hypervisor => RegisterAlias.SpHyp,
|
||||
Aarch32Mode.Undefined => RegisterAlias.SpUnd,
|
||||
_ => throw new ArgumentException($"No such AArch32Mode: {mode}", nameof(mode)),
|
||||
},
|
||||
14 => mode switch
|
||||
{
|
||||
Aarch32Mode.User or Aarch32Mode.Hypervisor or Aarch32Mode.System => RegisterAlias.LrUsr,
|
||||
Aarch32Mode.Fiq => RegisterAlias.LrFiq,
|
||||
Aarch32Mode.Irq => RegisterAlias.LrIrq,
|
||||
Aarch32Mode.Supervisor => RegisterAlias.LrSvc,
|
||||
Aarch32Mode.Abort => RegisterAlias.LrAbt,
|
||||
Aarch32Mode.Undefined => RegisterAlias.LrUnd,
|
||||
_ => throw new ArgumentException($"No such AArch32Mode: {mode}", nameof(mode)),
|
||||
},
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(regIndex), regIndex, null),
|
||||
#pragma warning restore IDE0055
|
||||
};
|
||||
}
|
||||
|
||||
public static bool IsA32Return(ArmEmitterContext context)
|
||||
{
|
||||
switch (context.CurrOp)
|
||||
return context.CurrOp switch
|
||||
{
|
||||
case IOpCode32MemMult op:
|
||||
return true; // Setting PC using LDM is nearly always a return.
|
||||
case OpCode32AluRsImm op:
|
||||
return op.Rm == RegisterAlias.Aarch32Lr;
|
||||
case OpCode32AluRsReg op:
|
||||
return op.Rm == RegisterAlias.Aarch32Lr;
|
||||
case OpCode32AluReg op:
|
||||
return op.Rm == RegisterAlias.Aarch32Lr;
|
||||
case OpCode32Mem op:
|
||||
return op.Rn == RegisterAlias.Aarch32Sp && op.WBack && !op.Index; // Setting PC to an address stored on the stack is nearly always a return.
|
||||
}
|
||||
return false;
|
||||
IOpCode32MemMult => true, // Setting PC using LDM is nearly always a return.
|
||||
OpCode32AluRsImm op => op.Rm == RegisterAlias.Aarch32Lr,
|
||||
OpCode32AluRsReg op => op.Rm == RegisterAlias.Aarch32Lr,
|
||||
OpCode32AluReg op => op.Rm == RegisterAlias.Aarch32Lr,
|
||||
OpCode32Mem op => op.Rn == RegisterAlias.Aarch32Sp && op.WBack && !op.Index, // Setting PC to an address stored on the stack is nearly always a return.
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
public static void EmitBxWritePc(ArmEmitterContext context, Operand pc, int sourceRegister = 0)
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace ARMeilleure.Instructions
|
|||
SetIntOrZR(context, op.Rd, Const(address));
|
||||
}
|
||||
|
||||
public static void Ldr(ArmEmitterContext context) => EmitLdr(context, signed: false);
|
||||
public static void Ldr(ArmEmitterContext context) => EmitLdr(context, signed: false);
|
||||
public static void Ldrs(ArmEmitterContext context) => EmitLdr(context, signed: true);
|
||||
|
||||
private static void EmitLdr(ArmEmitterContext context, bool signed)
|
||||
|
@ -89,7 +89,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand address = GetAddress(context);
|
||||
Operand address2 = GetAddress(context, 1L << op.Size);
|
||||
|
||||
EmitLoad(op.Rt, address);
|
||||
EmitLoad(op.Rt, address);
|
||||
EmitLoad(op.Rt2, address2);
|
||||
|
||||
EmitWBackIfNeeded(context, address);
|
||||
|
@ -113,7 +113,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand address = GetAddress(context);
|
||||
Operand address2 = GetAddress(context, 1L << op.Size);
|
||||
|
||||
EmitStore(context, address, op.Rt, op.Size);
|
||||
EmitStore(context, address, op.Rt, op.Size);
|
||||
EmitStore(context, address2, op.Rt2, op.Size);
|
||||
|
||||
EmitWBackIfNeeded(context, address);
|
||||
|
@ -126,42 +126,42 @@ namespace ARMeilleure.Instructions
|
|||
switch (context.CurrOp)
|
||||
{
|
||||
case OpCodeMemImm op:
|
||||
{
|
||||
address = context.Copy(GetIntOrSP(context, op.Rn));
|
||||
|
||||
// Pre-indexing.
|
||||
if (!op.PostIdx)
|
||||
{
|
||||
address = context.Add(address, Const(op.Immediate + addend));
|
||||
}
|
||||
else if (addend != 0)
|
||||
{
|
||||
address = context.Add(address, Const(addend));
|
||||
}
|
||||
address = context.Copy(GetIntOrSP(context, op.Rn));
|
||||
|
||||
break;
|
||||
}
|
||||
// Pre-indexing.
|
||||
if (!op.PostIdx)
|
||||
{
|
||||
address = context.Add(address, Const(op.Immediate + addend));
|
||||
}
|
||||
else if (addend != 0)
|
||||
{
|
||||
address = context.Add(address, Const(addend));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case OpCodeMemReg op:
|
||||
{
|
||||
Operand n = GetIntOrSP(context, op.Rn);
|
||||
|
||||
Operand m = GetExtendedM(context, op.Rm, op.IntType);
|
||||
|
||||
if (op.Shift)
|
||||
{
|
||||
m = context.ShiftLeft(m, Const(op.Size));
|
||||
Operand n = GetIntOrSP(context, op.Rn);
|
||||
|
||||
Operand m = GetExtendedM(context, op.Rm, op.IntType);
|
||||
|
||||
if (op.Shift)
|
||||
{
|
||||
m = context.ShiftLeft(m, Const(op.Size));
|
||||
}
|
||||
|
||||
address = context.Add(n, m);
|
||||
|
||||
if (addend != 0)
|
||||
{
|
||||
address = context.Add(address, Const(addend));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
address = context.Add(n, m);
|
||||
|
||||
if (addend != 0)
|
||||
{
|
||||
address = context.Add(address, Const(addend));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return address;
|
||||
|
@ -181,4 +181,4 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitMemoryHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -12,18 +11,18 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
static partial class InstEmit32
|
||||
{
|
||||
private const int ByteSizeLog2 = 0;
|
||||
private const int ByteSizeLog2 = 0;
|
||||
private const int HWordSizeLog2 = 1;
|
||||
private const int WordSizeLog2 = 2;
|
||||
private const int WordSizeLog2 = 2;
|
||||
private const int DWordSizeLog2 = 3;
|
||||
|
||||
[Flags]
|
||||
enum AccessType
|
||||
{
|
||||
Store = 0,
|
||||
Signed = 1,
|
||||
Load = 2,
|
||||
Ordered = 4,
|
||||
Store = 0,
|
||||
Signed = 1,
|
||||
Load = 2,
|
||||
Ordered = 4,
|
||||
Exclusive = 8,
|
||||
|
||||
LoadZx = Load,
|
||||
|
@ -47,7 +46,7 @@ namespace ARMeilleure.Instructions
|
|||
SetIntA32(context, op.Rn, context.Add(n, Const(op.PostOffset)));
|
||||
}
|
||||
|
||||
int mask = op.RegisterMask;
|
||||
int mask = op.RegisterMask;
|
||||
int offset = 0;
|
||||
|
||||
for (int register = 0; mask != 0; mask >>= 1, register++)
|
||||
|
@ -101,7 +100,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand baseAddress = context.Add(n, Const(op.Offset));
|
||||
|
||||
int mask = op.RegisterMask;
|
||||
int mask = op.RegisterMask;
|
||||
int offset = 0;
|
||||
|
||||
for (int register = 0; mask != 0; mask >>= 1, register++)
|
||||
|
@ -161,7 +160,7 @@ namespace ARMeilleure.Instructions
|
|||
if (op.Index || op.WBack)
|
||||
{
|
||||
temp = op.Add
|
||||
? context.Add (n, m)
|
||||
? context.Add(n, m)
|
||||
: context.Subtract(n, m);
|
||||
}
|
||||
|
||||
|
@ -200,7 +199,7 @@ namespace ARMeilleure.Instructions
|
|||
if (size == DWordSizeLog2)
|
||||
{
|
||||
Operand lblBigEndian = Label();
|
||||
Operand lblEnd = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
||||
context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
|
||||
|
||||
|
@ -233,7 +232,7 @@ namespace ARMeilleure.Instructions
|
|||
if (size == DWordSizeLog2)
|
||||
{
|
||||
Operand lblBigEndian = Label();
|
||||
Operand lblEnd = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
||||
context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
|
||||
|
||||
|
@ -262,4 +261,4 @@ namespace ARMeilleure.Instructions
|
|||
SetIntA32(context, op.Rd, Const(op.Immediate));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitMemoryExHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -15,10 +14,10 @@ namespace ARMeilleure.Instructions
|
|||
[Flags]
|
||||
private enum AccessType
|
||||
{
|
||||
None = 0,
|
||||
Ordered = 1,
|
||||
None = 0,
|
||||
Ordered = 1,
|
||||
Exclusive = 2,
|
||||
OrderedEx = Ordered | Exclusive
|
||||
OrderedEx = Ordered | Exclusive,
|
||||
}
|
||||
|
||||
public static void Clrex(ArmEmitterContext context)
|
||||
|
@ -34,10 +33,10 @@ namespace ARMeilleure.Instructions
|
|||
public static void Dmb(ArmEmitterContext context) => EmitBarrier(context);
|
||||
public static void Dsb(ArmEmitterContext context) => EmitBarrier(context);
|
||||
|
||||
public static void Ldar(ArmEmitterContext context) => EmitLdr(context, AccessType.Ordered);
|
||||
public static void Ldar(ArmEmitterContext context) => EmitLdr(context, AccessType.Ordered);
|
||||
public static void Ldaxr(ArmEmitterContext context) => EmitLdr(context, AccessType.OrderedEx);
|
||||
public static void Ldxr(ArmEmitterContext context) => EmitLdr(context, AccessType.Exclusive);
|
||||
public static void Ldxp(ArmEmitterContext context) => EmitLdp(context, AccessType.Exclusive);
|
||||
public static void Ldxr(ArmEmitterContext context) => EmitLdr(context, AccessType.Exclusive);
|
||||
public static void Ldxp(ArmEmitterContext context) => EmitLdp(context, AccessType.Exclusive);
|
||||
public static void Ldaxp(ArmEmitterContext context) => EmitLdp(context, AccessType.OrderedEx);
|
||||
|
||||
private static void EmitLdr(ArmEmitterContext context, AccessType accType)
|
||||
|
@ -54,7 +53,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeMemEx op = (OpCodeMemEx)context.CurrOp;
|
||||
|
||||
bool ordered = (accType & AccessType.Ordered) != 0;
|
||||
bool ordered = (accType & AccessType.Ordered) != 0;
|
||||
bool exclusive = (accType & AccessType.Exclusive) != 0;
|
||||
|
||||
if (ordered)
|
||||
|
@ -80,17 +79,17 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand valueHigh = context.ShiftRightUI(value, Const(32));
|
||||
|
||||
SetIntOrZR(context, op.Rt, valueLow);
|
||||
SetIntOrZR(context, op.Rt, valueLow);
|
||||
SetIntOrZR(context, op.Rt2, valueHigh);
|
||||
}
|
||||
else if (op.Size == 3)
|
||||
{
|
||||
Operand value = EmitLoadExclusive(context, address, exclusive, 4);
|
||||
|
||||
Operand valueLow = context.VectorExtract(OperandType.I64, value, 0);
|
||||
Operand valueLow = context.VectorExtract(OperandType.I64, value, 0);
|
||||
Operand valueHigh = context.VectorExtract(OperandType.I64, value, 1);
|
||||
|
||||
SetIntOrZR(context, op.Rt, valueLow);
|
||||
SetIntOrZR(context, op.Rt, valueLow);
|
||||
SetIntOrZR(context, op.Rt2, valueHigh);
|
||||
}
|
||||
else
|
||||
|
@ -112,10 +111,10 @@ namespace ARMeilleure.Instructions
|
|||
// Memory Prefetch, execute as no-op.
|
||||
}
|
||||
|
||||
public static void Stlr(ArmEmitterContext context) => EmitStr(context, AccessType.Ordered);
|
||||
public static void Stlr(ArmEmitterContext context) => EmitStr(context, AccessType.Ordered);
|
||||
public static void Stlxr(ArmEmitterContext context) => EmitStr(context, AccessType.OrderedEx);
|
||||
public static void Stxr(ArmEmitterContext context) => EmitStr(context, AccessType.Exclusive);
|
||||
public static void Stxp(ArmEmitterContext context) => EmitStp(context, AccessType.Exclusive);
|
||||
public static void Stxr(ArmEmitterContext context) => EmitStr(context, AccessType.Exclusive);
|
||||
public static void Stxp(ArmEmitterContext context) => EmitStp(context, AccessType.Exclusive);
|
||||
public static void Stlxp(ArmEmitterContext context) => EmitStp(context, AccessType.OrderedEx);
|
||||
|
||||
private static void EmitStr(ArmEmitterContext context, AccessType accType)
|
||||
|
@ -132,7 +131,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeMemEx op = (OpCodeMemEx)context.CurrOp;
|
||||
|
||||
bool ordered = (accType & AccessType.Ordered) != 0;
|
||||
bool ordered = (accType & AccessType.Ordered) != 0;
|
||||
bool exclusive = (accType & AccessType.Exclusive) != 0;
|
||||
|
||||
Operand address = context.Copy(GetIntOrSP(context, op.Rn));
|
||||
|
@ -153,8 +152,8 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else /* if (op.Size == 3) */
|
||||
{
|
||||
value = context.VectorInsert(context.VectorZero(), t, 0);
|
||||
value = context.VectorInsert(value, t2, 1);
|
||||
value = context.VectorInsert(context.VectorZero(), t, 0);
|
||||
value = context.VectorInsert(value, t2, 1);
|
||||
}
|
||||
|
||||
EmitStoreExclusive(context, address, value, exclusive, op.Size + 1, op.Rs, a32: false);
|
||||
|
@ -175,4 +174,4 @@ namespace ARMeilleure.Instructions
|
|||
context.MemoryBarrier();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -33,7 +32,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand arg0 = context.LoadArgument(OperandType.I64, 0);
|
||||
|
||||
Operand exAddrPtr = context.Add(arg0, Const((long)NativeContext.GetExclusiveAddressOffset()));
|
||||
Operand exAddrPtr = context.Add(arg0, Const((long)NativeContext.GetExclusiveAddressOffset()));
|
||||
Operand exValuePtr = context.Add(arg0, Const((long)NativeContext.GetExclusiveValueOffset()));
|
||||
|
||||
context.Store(exAddrPtr, context.BitwiseAnd(address, Const(address.Type, GetExclusiveAddressMask())));
|
||||
|
@ -118,14 +117,14 @@ namespace ARMeilleure.Instructions
|
|||
1 => context.Load16(exValuePtr),
|
||||
2 => context.Load(OperandType.I32, exValuePtr),
|
||||
3 => context.Load(OperandType.I64, exValuePtr),
|
||||
_ => context.Load(OperandType.V128, exValuePtr)
|
||||
_ => context.Load(OperandType.V128, exValuePtr),
|
||||
};
|
||||
|
||||
Operand currValue = size switch
|
||||
{
|
||||
0 => context.CompareAndSwap8(physAddr, exValue, value),
|
||||
1 => context.CompareAndSwap16(physAddr, exValue, value),
|
||||
_ => context.CompareAndSwap(physAddr, exValue, value)
|
||||
_ => context.CompareAndSwap(physAddr, exValue, value),
|
||||
};
|
||||
|
||||
// STEP 3: Check if we succeeded by comparing expected and in-memory values.
|
||||
|
@ -133,14 +132,14 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (size == 4)
|
||||
{
|
||||
Operand currValueLow = context.VectorExtract(OperandType.I64, currValue, 0);
|
||||
Operand currValueLow = context.VectorExtract(OperandType.I64, currValue, 0);
|
||||
Operand currValueHigh = context.VectorExtract(OperandType.I64, currValue, 1);
|
||||
|
||||
Operand exValueLow = context.VectorExtract(OperandType.I64, exValue, 0);
|
||||
Operand exValueLow = context.VectorExtract(OperandType.I64, exValue, 0);
|
||||
Operand exValueHigh = context.VectorExtract(OperandType.I64, exValue, 1);
|
||||
|
||||
storeFailed = context.BitwiseOr(
|
||||
context.ICompareNotEqual(currValueLow, exValueLow),
|
||||
context.ICompareNotEqual(currValueLow, exValueLow),
|
||||
context.ICompareNotEqual(currValueHigh, exValueHigh));
|
||||
}
|
||||
else
|
||||
|
|
|
@ -5,7 +5,6 @@ using ARMeilleure.Translation;
|
|||
using ARMeilleure.Translation.PTC;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -20,7 +19,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Zx,
|
||||
Sx32,
|
||||
Sx64
|
||||
Sx64,
|
||||
}
|
||||
|
||||
public static void EmitLoadZx(ArmEmitterContext context, Operand address, int rt, int size)
|
||||
|
@ -66,9 +65,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.SignExtend8 (destType, value); break;
|
||||
case 1: value = context.SignExtend16(destType, value); break;
|
||||
case 2: value = context.SignExtend32(destType, value); break;
|
||||
case 0:
|
||||
value = context.SignExtend8(destType, value);
|
||||
break;
|
||||
case 1:
|
||||
value = context.SignExtend16(destType, value);
|
||||
break;
|
||||
case 2:
|
||||
value = context.SignExtend32(destType, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,7 +133,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand temp = context.AllocateLocal(size == 3 ? OperandType.I64 : OperandType.I32);
|
||||
|
||||
Operand lblSlowPath = Label();
|
||||
Operand lblEnd = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
||||
Operand physAddr = EmitPtPointerLoad(context, address, lblSlowPath, write: false, size);
|
||||
|
||||
|
@ -136,10 +141,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.Load8 (physAddr); break;
|
||||
case 1: value = context.Load16(physAddr); break;
|
||||
case 2: value = context.Load (OperandType.I32, physAddr); break;
|
||||
case 3: value = context.Load (OperandType.I64, physAddr); break;
|
||||
case 0:
|
||||
value = context.Load8(physAddr);
|
||||
break;
|
||||
case 1:
|
||||
value = context.Load16(physAddr);
|
||||
break;
|
||||
case 2:
|
||||
value = context.Load(OperandType.I32, physAddr);
|
||||
break;
|
||||
case 3:
|
||||
value = context.Load(OperandType.I64, physAddr);
|
||||
break;
|
||||
}
|
||||
|
||||
context.Copy(temp, value);
|
||||
|
@ -161,7 +174,7 @@ namespace ARMeilleure.Instructions
|
|||
private static void EmitReadInt(ArmEmitterContext context, Operand address, int rt, int size)
|
||||
{
|
||||
Operand lblSlowPath = Label();
|
||||
Operand lblEnd = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
||||
Operand physAddr = EmitPtPointerLoad(context, address, lblSlowPath, write: false, size);
|
||||
|
||||
|
@ -169,10 +182,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.Load8 (physAddr); break;
|
||||
case 1: value = context.Load16(physAddr); break;
|
||||
case 2: value = context.Load (OperandType.I32, physAddr); break;
|
||||
case 3: value = context.Load (OperandType.I64, physAddr); break;
|
||||
case 0:
|
||||
value = context.Load8(physAddr);
|
||||
break;
|
||||
case 1:
|
||||
value = context.Load16(physAddr);
|
||||
break;
|
||||
case 2:
|
||||
value = context.Load(OperandType.I32, physAddr);
|
||||
break;
|
||||
case 3:
|
||||
value = context.Load(OperandType.I64, physAddr);
|
||||
break;
|
||||
}
|
||||
|
||||
SetInt(context, rt, value);
|
||||
|
@ -204,7 +225,7 @@ namespace ARMeilleure.Instructions
|
|||
1 => context.Load16(physAddr),
|
||||
2 => context.Load(OperandType.I32, physAddr),
|
||||
3 => context.Load(OperandType.I64, physAddr),
|
||||
_ => context.Load(OperandType.V128, physAddr)
|
||||
_ => context.Load(OperandType.V128, physAddr),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -217,7 +238,7 @@ namespace ARMeilleure.Instructions
|
|||
int size)
|
||||
{
|
||||
Operand lblSlowPath = Label();
|
||||
Operand lblEnd = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
||||
Operand physAddr = EmitPtPointerLoad(context, address, lblSlowPath, write: false, size);
|
||||
|
||||
|
@ -225,11 +246,21 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.VectorInsert8 (vector, context.Load8(physAddr), elem); break;
|
||||
case 1: value = context.VectorInsert16(vector, context.Load16(physAddr), elem); break;
|
||||
case 2: value = context.VectorInsert (vector, context.Load(OperandType.I32, physAddr), elem); break;
|
||||
case 3: value = context.VectorInsert (vector, context.Load(OperandType.I64, physAddr), elem); break;
|
||||
case 4: value = context.Load (OperandType.V128, physAddr); break;
|
||||
case 0:
|
||||
value = context.VectorInsert8(vector, context.Load8(physAddr), elem);
|
||||
break;
|
||||
case 1:
|
||||
value = context.VectorInsert16(vector, context.Load16(physAddr), elem);
|
||||
break;
|
||||
case 2:
|
||||
value = context.VectorInsert(vector, context.Load(OperandType.I32, physAddr), elem);
|
||||
break;
|
||||
case 3:
|
||||
value = context.VectorInsert(vector, context.Load(OperandType.I64, physAddr), elem);
|
||||
break;
|
||||
case 4:
|
||||
value = context.Load(OperandType.V128, physAddr);
|
||||
break;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(rt), value);
|
||||
|
@ -254,7 +285,7 @@ namespace ARMeilleure.Instructions
|
|||
private static void EmitWriteInt(ArmEmitterContext context, Operand address, int rt, int size)
|
||||
{
|
||||
Operand lblSlowPath = Label();
|
||||
Operand lblEnd = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
||||
Operand physAddr = EmitPtPointerLoad(context, address, lblSlowPath, write: true, size);
|
||||
|
||||
|
@ -267,10 +298,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: context.Store8 (physAddr, value); break;
|
||||
case 1: context.Store16(physAddr, value); break;
|
||||
case 2: context.Store (physAddr, value); break;
|
||||
case 3: context.Store (physAddr, value); break;
|
||||
case 0:
|
||||
context.Store8(physAddr, value);
|
||||
break;
|
||||
case 1:
|
||||
context.Store16(physAddr, value);
|
||||
break;
|
||||
case 2:
|
||||
context.Store(physAddr, value);
|
||||
break;
|
||||
case 3:
|
||||
context.Store(physAddr, value);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!context.Memory.Type.IsHostMapped())
|
||||
|
@ -321,7 +360,7 @@ namespace ARMeilleure.Instructions
|
|||
int size)
|
||||
{
|
||||
Operand lblSlowPath = Label();
|
||||
Operand lblEnd = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
||||
Operand physAddr = EmitPtPointerLoad(context, address, lblSlowPath, write: true, size);
|
||||
|
||||
|
@ -329,11 +368,21 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: context.Store8 (physAddr, context.VectorExtract8(value, elem)); break;
|
||||
case 1: context.Store16(physAddr, context.VectorExtract16(value, elem)); break;
|
||||
case 2: context.Store (physAddr, context.VectorExtract(OperandType.I32, value, elem)); break;
|
||||
case 3: context.Store (physAddr, context.VectorExtract(OperandType.I64, value, elem)); break;
|
||||
case 4: context.Store (physAddr, value); break;
|
||||
case 0:
|
||||
context.Store8(physAddr, context.VectorExtract8(value, elem));
|
||||
break;
|
||||
case 1:
|
||||
context.Store16(physAddr, context.VectorExtract16(value, elem));
|
||||
break;
|
||||
case 2:
|
||||
context.Store(physAddr, context.VectorExtract(OperandType.I32, value, elem));
|
||||
break;
|
||||
case 3:
|
||||
context.Store(physAddr, context.VectorExtract(OperandType.I64, value, elem));
|
||||
break;
|
||||
case 4:
|
||||
context.Store(physAddr, value);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!context.Memory.Type.IsHostMapped())
|
||||
|
@ -464,10 +513,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break;
|
||||
case 0:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte));
|
||||
break;
|
||||
case 1:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64));
|
||||
break;
|
||||
}
|
||||
|
||||
return context.Call(info, address);
|
||||
|
@ -485,21 +542,39 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break;
|
||||
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)); break;
|
||||
case 0:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte));
|
||||
break;
|
||||
case 1:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64));
|
||||
break;
|
||||
case 4:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128));
|
||||
break;
|
||||
}
|
||||
|
||||
Operand value = context.Call(info, address);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.VectorInsert8 (vector, value, elem); break;
|
||||
case 1: value = context.VectorInsert16(vector, value, elem); break;
|
||||
case 2: value = context.VectorInsert (vector, value, elem); break;
|
||||
case 3: value = context.VectorInsert (vector, value, elem); break;
|
||||
case 0:
|
||||
value = context.VectorInsert8(vector, value, elem);
|
||||
break;
|
||||
case 1:
|
||||
value = context.VectorInsert16(vector, value, elem);
|
||||
break;
|
||||
case 2:
|
||||
value = context.VectorInsert(vector, value, elem);
|
||||
break;
|
||||
case 3:
|
||||
value = context.VectorInsert(vector, value, elem);
|
||||
break;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(rt), value);
|
||||
|
@ -511,10 +586,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)); break;
|
||||
case 0:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte));
|
||||
break;
|
||||
case 1:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64));
|
||||
break;
|
||||
}
|
||||
|
||||
Operand value = GetInt(context, rt);
|
||||
|
@ -538,11 +621,21 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)); break;
|
||||
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128)); break;
|
||||
case 0:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte));
|
||||
break;
|
||||
case 1:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64));
|
||||
break;
|
||||
case 4:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128));
|
||||
break;
|
||||
}
|
||||
|
||||
Operand value = default;
|
||||
|
@ -551,10 +644,18 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.VectorExtract8 (GetVec(rt), elem); break;
|
||||
case 1: value = context.VectorExtract16(GetVec(rt), elem); break;
|
||||
case 2: value = context.VectorExtract (OperandType.I32, GetVec(rt), elem); break;
|
||||
case 3: value = context.VectorExtract (OperandType.I64, GetVec(rt), elem); break;
|
||||
case 0:
|
||||
value = context.VectorExtract8(GetVec(rt), elem);
|
||||
break;
|
||||
case 1:
|
||||
value = context.VectorExtract16(GetVec(rt), elem);
|
||||
break;
|
||||
case 2:
|
||||
value = context.VectorExtract(OperandType.I32, GetVec(rt), elem);
|
||||
break;
|
||||
case 3:
|
||||
value = context.VectorExtract(OperandType.I64, GetVec(rt), elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -585,18 +686,14 @@ namespace ARMeilleure.Instructions
|
|||
// ARM32 helpers.
|
||||
public static Operand GetMemM(ArmEmitterContext context, bool setCarry = true)
|
||||
{
|
||||
switch (context.CurrOp)
|
||||
return context.CurrOp switch
|
||||
{
|
||||
case IOpCode32MemRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
|
||||
|
||||
case IOpCode32MemReg op: return GetIntA32(context, op.Rm);
|
||||
|
||||
case IOpCode32Mem op: return Const(op.Immediate);
|
||||
|
||||
case OpCode32SimdMemImm op: return Const(op.Immediate);
|
||||
|
||||
default: throw InvalidOpCodeType(context.CurrOp);
|
||||
}
|
||||
IOpCode32MemRsImm op => GetMShiftedByImmediate(context, op, setCarry),
|
||||
IOpCode32MemReg op => GetIntA32(context, op.Rm),
|
||||
IOpCode32Mem op => Const(op.Immediate),
|
||||
OpCode32SimdMemImm op => Const(op.Immediate),
|
||||
_ => throw InvalidOpCodeType(context.CurrOp),
|
||||
};
|
||||
}
|
||||
|
||||
private static Exception InvalidOpCodeType(OpCode opCode)
|
||||
|
@ -614,9 +711,15 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsr: shift = 32; break;
|
||||
case ShiftType.Asr: shift = 32; break;
|
||||
case ShiftType.Ror: shift = 1; break;
|
||||
case ShiftType.Lsr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
shift = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,9 +729,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsl: m = InstEmitAluHelper.GetLslC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Lsr: m = InstEmitAluHelper.GetLsrC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Asr: m = InstEmitAluHelper.GetAsrC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Lsl:
|
||||
m = InstEmitAluHelper.GetLslC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Lsr:
|
||||
m = InstEmitAluHelper.GetLsrC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
m = InstEmitAluHelper.GetAsrC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
if (op.Immediate != 0)
|
||||
{
|
||||
|
|
|
@ -38,4 +38,4 @@ namespace ARMeilleure.Instructions
|
|||
SetIntOrZR(context, op.Rd, Const(op.GetOperandType(), op.Immediate));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ using ARMeilleure.Decoders;
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
|
@ -33,14 +33,15 @@ namespace ARMeilleure.Instructions
|
|||
public static void Umsubl(ArmEmitterContext context) => EmitMull(context, MullFlags.Subtract);
|
||||
|
||||
[Flags]
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
private enum MullFlags
|
||||
{
|
||||
Subtract = 0,
|
||||
Add = 1 << 0,
|
||||
Signed = 1 << 1,
|
||||
Add = 1 << 0,
|
||||
Signed = 1 << 1,
|
||||
|
||||
SignedAdd = Signed | Add,
|
||||
SignedSubtract = Signed | Subtract
|
||||
SignedAdd = Signed | Add,
|
||||
SignedSubtract = Signed | Subtract,
|
||||
}
|
||||
|
||||
private static void EmitMull(ArmEmitterContext context, MullFlags flags)
|
||||
|
@ -97,4 +98,4 @@ namespace ARMeilleure.Instructions
|
|||
SetIntOrZR(context, op.Rd, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitAluHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -20,7 +19,7 @@ namespace ARMeilleure.Instructions
|
|||
Signed = 1 << 2,
|
||||
|
||||
SignedAdd = Signed | Add,
|
||||
SignedSubtract = Signed | Subtract
|
||||
SignedSubtract = Signed | Subtract,
|
||||
}
|
||||
|
||||
public static void Mla(ArmEmitterContext context)
|
||||
|
@ -287,14 +286,14 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
|
||||
|
||||
Operand n = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rn));
|
||||
Operand m = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rm));
|
||||
Operand n = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rn));
|
||||
Operand m = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rm));
|
||||
Operand dHi = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.RdHi));
|
||||
Operand dLo = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.RdLo));
|
||||
|
||||
Operand res = context.Multiply(n, m);
|
||||
res = context.Add(res, dHi);
|
||||
res = context.Add(res, dLo);
|
||||
res = context.Add(res, dHi);
|
||||
res = context.Add(res, dLo);
|
||||
|
||||
Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32)));
|
||||
Operand lo = context.ConvertI64ToI32(res);
|
||||
|
|
|
@ -7,7 +7,6 @@ using ARMeilleure.State;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
|
||||
|
@ -185,11 +184,12 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
int eSize = 8 << op.Size;
|
||||
|
||||
Operand res = eSize switch {
|
||||
8 => Clz_V_I8 (context, GetVec(op.Rn)),
|
||||
Operand res = eSize switch
|
||||
{
|
||||
8 => Clz_V_I8(context, GetVec(op.Rn)),
|
||||
16 => Clz_V_I16(context, GetVec(op.Rn)),
|
||||
32 => Clz_V_I32(context, GetVec(op.Rn)),
|
||||
_ => default
|
||||
_ => default,
|
||||
};
|
||||
|
||||
if (res != default)
|
||||
|
@ -230,14 +230,14 @@ namespace ARMeilleure.Instructions
|
|||
Operand clzTable = X86GetScalar(context, 0x01_01_01_01_02_02_03_04);
|
||||
|
||||
Operand maskLow = X86GetAllElements(context, 0x0f_0f_0f_0f);
|
||||
Operand c04 = X86GetAllElements(context, 0x04_04_04_04);
|
||||
Operand c04 = X86GetAllElements(context, 0x04_04_04_04);
|
||||
|
||||
// CLZ of low 4 bits of elements in arg.
|
||||
Operand loClz = context.AddIntrinsic(Intrinsic.X86Pshufb, clzTable, arg);
|
||||
|
||||
// Get the high 4 bits of elements in arg.
|
||||
Operand hiArg = context.AddIntrinsic(Intrinsic.X86Psrlw, arg, Const(4));
|
||||
hiArg = context.AddIntrinsic(Intrinsic.X86Pand, hiArg, maskLow);
|
||||
hiArg = context.AddIntrinsic(Intrinsic.X86Pand, hiArg, maskLow);
|
||||
|
||||
// CLZ of high 4 bits of elements in arg.
|
||||
Operand hiClz = context.AddIntrinsic(Intrinsic.X86Pshufb, clzTable, hiArg);
|
||||
|
@ -257,8 +257,8 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
Operand maskSwap = X86GetElements(context, 0x80_0f_80_0d_80_0b_80_09, 0x80_07_80_05_80_03_80_01);
|
||||
Operand maskLow = X86GetAllElements(context, 0x00ff_00ff);
|
||||
Operand c0008 = X86GetAllElements(context, 0x0008_0008);
|
||||
Operand maskLow = X86GetAllElements(context, 0x00ff_00ff);
|
||||
Operand c0008 = X86GetAllElements(context, 0x0008_0008);
|
||||
|
||||
// CLZ pair of high 8 and low 8 bits of elements in arg.
|
||||
Operand hiloClz = Clz_V_I8(context, arg);
|
||||
|
@ -282,12 +282,14 @@ namespace ARMeilleure.Instructions
|
|||
return default;
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Operand AddVectorI32(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Paddd, op0, op1);
|
||||
Operand SubVectorI32(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Psubd, op0, op1);
|
||||
Operand ShiftRightVectorUI32(Operand op0, int imm8) => context.AddIntrinsic(Intrinsic.X86Psrld, op0, Const(imm8));
|
||||
Operand OrVector(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Por, op0, op1);
|
||||
Operand AndVector(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Pand, op0, op1);
|
||||
Operand NotVector(Operand op0) => context.AddIntrinsic(Intrinsic.X86Pandn, op0, context.VectorOne());
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
Operand c55555555 = X86GetAllElements(context, 0x55555555);
|
||||
Operand c33333333 = X86GetAllElements(context, 0x33333333);
|
||||
|
@ -311,24 +313,24 @@ namespace ARMeilleure.Instructions
|
|||
// Count leading 1s, which is the population count.
|
||||
tmp0 = ShiftRightVectorUI32(res, 1);
|
||||
tmp0 = AndVector(tmp0, c55555555);
|
||||
res = SubVectorI32(res, tmp0);
|
||||
res = SubVectorI32(res, tmp0);
|
||||
|
||||
tmp0 = ShiftRightVectorUI32(res, 2);
|
||||
tmp0 = AndVector(tmp0, c33333333);
|
||||
tmp1 = AndVector(res, c33333333);
|
||||
res = AddVectorI32(tmp0, tmp1);
|
||||
res = AddVectorI32(tmp0, tmp1);
|
||||
|
||||
tmp0 = ShiftRightVectorUI32(res, 4);
|
||||
tmp0 = AddVectorI32(tmp0, res);
|
||||
res = AndVector(tmp0, c0f0f0f0f);
|
||||
res = AndVector(tmp0, c0f0f0f0f);
|
||||
|
||||
tmp0 = ShiftRightVectorUI32(res, 8);
|
||||
res = AddVectorI32(tmp0, res);
|
||||
res = AddVectorI32(tmp0, res);
|
||||
|
||||
tmp0 = ShiftRightVectorUI32(res, 16);
|
||||
res = AddVectorI32(tmp0, res);
|
||||
res = AddVectorI32(tmp0, res);
|
||||
|
||||
res = AndVector(res, c0000003f);
|
||||
res = AndVector(res, c0000003f);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -2436,8 +2438,8 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (sizeF == 0)
|
||||
{
|
||||
Operand maskHalf = X86GetScalar(context, 0.5f);
|
||||
Operand maskThree = X86GetScalar(context, 3f);
|
||||
Operand maskHalf = X86GetScalar(context, 0.5f);
|
||||
Operand maskThree = X86GetScalar(context, 3f);
|
||||
Operand maskOneHalf = X86GetScalar(context, 1.5f);
|
||||
|
||||
if (Optimizations.UseFma)
|
||||
|
@ -2457,8 +2459,8 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else /* if (sizeF == 1) */
|
||||
{
|
||||
Operand maskHalf = X86GetScalar(context, 0.5d);
|
||||
Operand maskThree = X86GetScalar(context, 3d);
|
||||
Operand maskHalf = X86GetScalar(context, 0.5d);
|
||||
Operand maskThree = X86GetScalar(context, 3d);
|
||||
Operand maskOneHalf = X86GetScalar(context, 1.5d);
|
||||
|
||||
if (Optimizations.UseFma)
|
||||
|
@ -2505,8 +2507,8 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (sizeF == 0)
|
||||
{
|
||||
Operand maskHalf = X86GetAllElements(context, 0.5f);
|
||||
Operand maskThree = X86GetAllElements(context, 3f);
|
||||
Operand maskHalf = X86GetAllElements(context, 0.5f);
|
||||
Operand maskThree = X86GetAllElements(context, 3f);
|
||||
Operand maskOneHalf = X86GetAllElements(context, 1.5f);
|
||||
|
||||
if (Optimizations.UseFma)
|
||||
|
@ -2519,7 +2521,7 @@ namespace ARMeilleure.Instructions
|
|||
res = context.AddIntrinsic(Intrinsic.X86Subps, maskThree, res);
|
||||
}
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulps, maskHalf, res);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulps, maskHalf, res);
|
||||
res = EmitSse41RecipStepSelectOpF(context, n, m, res, maskOneHalf, scalar: false, sizeF);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd64)
|
||||
|
@ -2531,8 +2533,8 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else /* if (sizeF == 1) */
|
||||
{
|
||||
Operand maskHalf = X86GetAllElements(context, 0.5d);
|
||||
Operand maskThree = X86GetAllElements(context, 3d);
|
||||
Operand maskHalf = X86GetAllElements(context, 0.5d);
|
||||
Operand maskThree = X86GetAllElements(context, 3d);
|
||||
Operand maskOneHalf = X86GetAllElements(context, 1.5d);
|
||||
|
||||
if (Optimizations.UseFma)
|
||||
|
@ -2545,7 +2547,7 @@ namespace ARMeilleure.Instructions
|
|||
res = context.AddIntrinsic(Intrinsic.X86Subpd, maskThree, res);
|
||||
}
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulpd, maskHalf, res);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulpd, maskHalf, res);
|
||||
res = EmitSse41RecipStepSelectOpF(context, n, m, res, maskOneHalf, scalar: false, sizeF);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
|
@ -2824,10 +2826,10 @@ namespace ARMeilleure.Instructions
|
|||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
Operand mask = context.AddIntrinsic(Intrinsic.X86Psllw, n, Const(15 - i));
|
||||
mask = context.AddIntrinsic(Intrinsic.X86Psraw, mask, Const(15));
|
||||
mask = context.AddIntrinsic(Intrinsic.X86Psraw, mask, Const(15));
|
||||
|
||||
Operand tmp = context.AddIntrinsic(Intrinsic.X86Psllw, m, Const(i));
|
||||
tmp = context.AddIntrinsic(Intrinsic.X86Pand, tmp, mask);
|
||||
tmp = context.AddIntrinsic(Intrinsic.X86Pand, tmp, mask);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Pxor, res, tmp);
|
||||
}
|
||||
|
@ -2839,12 +2841,12 @@ namespace ARMeilleure.Instructions
|
|||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
Operand mask = context.AddIntrinsic(Intrinsic.X86Movlhps, n, n);
|
||||
mask = context.AddIntrinsic(Intrinsic.X86Psllq, mask, Const(63 - i));
|
||||
mask = context.AddIntrinsic(Intrinsic.X86Psrlq, mask, Const(63));
|
||||
mask = context.AddIntrinsic(Intrinsic.X86Psubq, zero, mask);
|
||||
mask = context.AddIntrinsic(Intrinsic.X86Psllq, mask, Const(63 - i));
|
||||
mask = context.AddIntrinsic(Intrinsic.X86Psrlq, mask, Const(63));
|
||||
mask = context.AddIntrinsic(Intrinsic.X86Psubq, zero, mask);
|
||||
|
||||
Operand tmp = EmitSse2Sll_128(context, m, i);
|
||||
tmp = context.AddIntrinsic(Intrinsic.X86Pand, tmp, mask);
|
||||
tmp = context.AddIntrinsic(Intrinsic.X86Pand, tmp, mask);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Pxor, res, tmp);
|
||||
}
|
||||
|
@ -3119,7 +3121,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Pand, n, m);
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Pand, n, m);
|
||||
Operand res2 = context.AddIntrinsic(Intrinsic.X86Pxor, n, m);
|
||||
|
||||
Intrinsic shiftInst = op.Size == 1 ? Intrinsic.X86Psraw : Intrinsic.X86Psrad;
|
||||
|
@ -4058,7 +4060,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Pand, n, m);
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Pand, n, m);
|
||||
Operand res2 = context.AddIntrinsic(Intrinsic.X86Pxor, n, m);
|
||||
|
||||
Intrinsic shiftInst = op.Size == 1 ? Intrinsic.X86Psrlw : Intrinsic.X86Psrld;
|
||||
|
@ -4594,7 +4596,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
int pairIndex = index << 1;
|
||||
|
||||
Operand ne0 = EmitVectorExtract(context, op.Rn, pairIndex, op.Size, signed);
|
||||
Operand ne0 = EmitVectorExtract(context, op.Rn, pairIndex, op.Size, signed);
|
||||
Operand ne1 = EmitVectorExtract(context, op.Rn, pairIndex + 1, op.Size, signed);
|
||||
|
||||
Operand e = context.Add(ne0, ne1);
|
||||
|
@ -4686,7 +4688,7 @@ namespace ARMeilleure.Instructions
|
|||
Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64);
|
||||
|
||||
Operand cmp = signed
|
||||
? context.ICompareGreaterOrEqual (op1, op2)
|
||||
? context.ICompareGreaterOrEqual(op1, op2)
|
||||
: context.ICompareGreaterOrEqualUI(op1, op2);
|
||||
|
||||
return context.ConditionalSelect(cmp, op1, op2);
|
||||
|
@ -4697,7 +4699,7 @@ namespace ARMeilleure.Instructions
|
|||
Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64);
|
||||
|
||||
Operand cmp = signed
|
||||
? context.ICompareLessOrEqual (op1, op2)
|
||||
? context.ICompareLessOrEqual(op1, op2)
|
||||
: context.ICompareLessOrEqualUI(op1, op2);
|
||||
|
||||
return context.ConditionalSelect(cmp, op1, op2);
|
||||
|
@ -4852,10 +4854,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand mask1 = context.AddIntrinsic(Intrinsic.X86Cmpps, opF, opF, Const((int)CmpCondition.UnorderedQ));
|
||||
|
||||
Operand mask2 = context.AddIntrinsic(Intrinsic.X86Pand, opF, qMask);
|
||||
mask2 = context.AddIntrinsic(Intrinsic.X86Cmpps, mask2, qMask, Const((int)CmpCondition.Equal));
|
||||
Operand mask2 = context.AddIntrinsic(Intrinsic.X86Pand, opF, qMask);
|
||||
mask2 = context.AddIntrinsic(Intrinsic.X86Cmpps, mask2, qMask, Const((int)CmpCondition.Equal));
|
||||
|
||||
qNaNMask = isQNaN == null || (bool)isQNaN ? context.AddIntrinsic(Intrinsic.X86Andps, mask2, mask1) : default;
|
||||
qNaNMask = isQNaN == null || (bool)isQNaN ? context.AddIntrinsic(Intrinsic.X86Andps, mask2, mask1) : default;
|
||||
sNaNMask = isQNaN == null || !(bool)isQNaN ? context.AddIntrinsic(Intrinsic.X86Andnps, mask2, mask1) : default;
|
||||
}
|
||||
else /* if ((op.Size & 1) == 1) */
|
||||
|
@ -4866,10 +4868,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand mask1 = context.AddIntrinsic(Intrinsic.X86Cmppd, opF, opF, Const((int)CmpCondition.UnorderedQ));
|
||||
|
||||
Operand mask2 = context.AddIntrinsic(Intrinsic.X86Pand, opF, qMask);
|
||||
mask2 = context.AddIntrinsic(Intrinsic.X86Cmppd, mask2, qMask, Const((int)CmpCondition.Equal));
|
||||
Operand mask2 = context.AddIntrinsic(Intrinsic.X86Pand, opF, qMask);
|
||||
mask2 = context.AddIntrinsic(Intrinsic.X86Cmppd, mask2, qMask, Const((int)CmpCondition.Equal));
|
||||
|
||||
qNaNMask = isQNaN == null || (bool)isQNaN ? context.AddIntrinsic(Intrinsic.X86Andpd, mask2, mask1) : default;
|
||||
qNaNMask = isQNaN == null || (bool)isQNaN ? context.AddIntrinsic(Intrinsic.X86Andpd, mask2, mask1) : default;
|
||||
sNaNMask = isQNaN == null || !(bool)isQNaN ? context.AddIntrinsic(Intrinsic.X86Andnpd, mask2, mask1) : default;
|
||||
}
|
||||
}
|
||||
|
@ -4895,11 +4897,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand qMask = scalar ? X86GetScalar(context, 1 << QBit) : X86GetAllElements(context, 1 << QBit);
|
||||
|
||||
Operand resNaNMask = context.AddIntrinsic(Intrinsic.X86Pandn, mSNaNMask, nQNaNMask);
|
||||
resNaNMask = context.AddIntrinsic(Intrinsic.X86Por, resNaNMask, nSNaNMask);
|
||||
Operand resNaNMask = context.AddIntrinsic(Intrinsic.X86Pandn, mSNaNMask, nQNaNMask);
|
||||
resNaNMask = context.AddIntrinsic(Intrinsic.X86Por, resNaNMask, nSNaNMask);
|
||||
|
||||
Operand resNaN = context.AddIntrinsic(Intrinsic.X86Blendvps, mCopy, nCopy, resNaNMask);
|
||||
resNaN = context.AddIntrinsic(Intrinsic.X86Por, resNaN, qMask);
|
||||
resNaN = context.AddIntrinsic(Intrinsic.X86Por, resNaN, qMask);
|
||||
|
||||
Operand resMask = context.AddIntrinsic(Intrinsic.X86Cmpps, nCopy, mCopy, Const((int)CmpCondition.OrderedQ));
|
||||
|
||||
|
@ -4929,11 +4931,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand qMask = scalar ? X86GetScalar(context, 1L << QBit) : X86GetAllElements(context, 1L << QBit);
|
||||
|
||||
Operand resNaNMask = context.AddIntrinsic(Intrinsic.X86Pandn, mSNaNMask, nQNaNMask);
|
||||
resNaNMask = context.AddIntrinsic(Intrinsic.X86Por, resNaNMask, nSNaNMask);
|
||||
Operand resNaNMask = context.AddIntrinsic(Intrinsic.X86Pandn, mSNaNMask, nQNaNMask);
|
||||
resNaNMask = context.AddIntrinsic(Intrinsic.X86Por, resNaNMask, nSNaNMask);
|
||||
|
||||
Operand resNaN = context.AddIntrinsic(Intrinsic.X86Blendvpd, mCopy, nCopy, resNaNMask);
|
||||
resNaN = context.AddIntrinsic(Intrinsic.X86Por, resNaN, qMask);
|
||||
resNaN = context.AddIntrinsic(Intrinsic.X86Por, resNaN, qMask);
|
||||
|
||||
Operand resMask = context.AddIntrinsic(Intrinsic.X86Cmppd, nCopy, mCopy, Const((int)CmpCondition.OrderedQ));
|
||||
|
||||
|
@ -4964,10 +4966,10 @@ namespace ARMeilleure.Instructions
|
|||
Operand mask = X86GetAllElements(context, -0f);
|
||||
|
||||
Operand res = context.AddIntrinsic(isMax ? Intrinsic.X86Maxps : Intrinsic.X86Minps, n, m);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Andnps, mask, res);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Andnps, mask, res);
|
||||
|
||||
Operand resSign = context.AddIntrinsic(isMax ? Intrinsic.X86Pand : Intrinsic.X86Por, n, m);
|
||||
resSign = context.AddIntrinsic(Intrinsic.X86Andps, mask, resSign);
|
||||
resSign = context.AddIntrinsic(Intrinsic.X86Andps, mask, resSign);
|
||||
|
||||
return context.AddIntrinsic(Intrinsic.X86Por, res, resSign);
|
||||
}
|
||||
|
@ -4976,10 +4978,10 @@ namespace ARMeilleure.Instructions
|
|||
Operand mask = X86GetAllElements(context, -0d);
|
||||
|
||||
Operand res = context.AddIntrinsic(isMax ? Intrinsic.X86Maxpd : Intrinsic.X86Minpd, n, m);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Andnpd, mask, res);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Andnpd, mask, res);
|
||||
|
||||
Operand resSign = context.AddIntrinsic(isMax ? Intrinsic.X86Pand : Intrinsic.X86Por, n, m);
|
||||
resSign = context.AddIntrinsic(Intrinsic.X86Andpd, mask, resSign);
|
||||
resSign = context.AddIntrinsic(Intrinsic.X86Andpd, mask, resSign);
|
||||
|
||||
return context.AddIntrinsic(Intrinsic.X86Por, res, resSign);
|
||||
}
|
||||
|
@ -5003,7 +5005,7 @@ namespace ARMeilleure.Instructions
|
|||
if (sizeF == 0)
|
||||
{
|
||||
Operand negInfMask = scalar
|
||||
? X86GetScalar (context, isMaxNum ? float.NegativeInfinity : float.PositiveInfinity)
|
||||
? X86GetScalar(context, isMaxNum ? float.NegativeInfinity : float.PositiveInfinity)
|
||||
: X86GetAllElements(context, isMaxNum ? float.NegativeInfinity : float.PositiveInfinity);
|
||||
|
||||
Operand nMask = context.AddIntrinsic(Intrinsic.X86Andnps, mQNaNMask, nQNaNMask);
|
||||
|
@ -5038,7 +5040,7 @@ namespace ARMeilleure.Instructions
|
|||
else /* if (sizeF == 1) */
|
||||
{
|
||||
Operand negInfMask = scalar
|
||||
? X86GetScalar (context, isMaxNum ? double.NegativeInfinity : double.PositiveInfinity)
|
||||
? X86GetScalar(context, isMaxNum ? double.NegativeInfinity : double.PositiveInfinity)
|
||||
: X86GetAllElements(context, isMaxNum ? double.NegativeInfinity : double.PositiveInfinity);
|
||||
|
||||
Operand nMask = context.AddIntrinsic(Intrinsic.X86Andnpd, mQNaNMask, nQNaNMask);
|
||||
|
@ -5072,7 +5074,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
None,
|
||||
Add,
|
||||
Subtract
|
||||
Subtract,
|
||||
}
|
||||
|
||||
private static void EmitSse41VectorMul_AddSub(ArmEmitterContext context, AddSub addSub)
|
||||
|
@ -5187,10 +5189,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Intrinsic subInst = X86PsubInstruction[size];
|
||||
|
||||
Operand res = context.AddIntrinsic(subInst, n, m);
|
||||
Operand res = context.AddIntrinsic(subInst, n, m);
|
||||
Operand res2 = context.AddIntrinsic(subInst, m, n);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Pand, cmpMask, res);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Pand, cmpMask, res);
|
||||
res2 = context.AddIntrinsic(Intrinsic.X86Pandn, cmpMask, res2);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Por, res, res2);
|
||||
|
@ -5214,7 +5216,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
Operand high = context.AddIntrinsic(Intrinsic.X86Pslldq, op, Const(8));
|
||||
high = context.AddIntrinsic(Intrinsic.X86Psrlq, high, Const(64 - shift));
|
||||
high = context.AddIntrinsic(Intrinsic.X86Psrlq, high, Const(64 - shift));
|
||||
|
||||
Operand low = context.AddIntrinsic(Intrinsic.X86Psllq, op, Const(shift));
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
|
@ -190,7 +189,7 @@ namespace ARMeilleure.Instructions
|
|||
2 => context.Multiply(context.ZeroExtend32(OperandType.I64, insert), Const(0x0000000100000001u)),
|
||||
1 => context.Multiply(context.ZeroExtend16(OperandType.I64, insert), Const(0x0001000100010001u)),
|
||||
0 => context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u)),
|
||||
_ => throw new InvalidOperationException($"Invalid Vdup size \"{op.Size}\".")
|
||||
_ => throw new InvalidOperationException($"Invalid Vdup size \"{op.Size}\"."),
|
||||
};
|
||||
|
||||
InsertScalar(context, op.Vd, insert);
|
||||
|
@ -212,7 +211,7 @@ namespace ARMeilleure.Instructions
|
|||
2 => context.Multiply(context.ZeroExtend32(OperandType.I64, insert), Const(0x0000000100000001u)),
|
||||
1 => context.Multiply(context.ZeroExtend16(OperandType.I64, insert), Const(0x0001000100010001u)),
|
||||
0 => context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u)),
|
||||
_ => throw new InvalidOperationException($"Invalid Vdup size \"{op.Size}\".")
|
||||
_ => throw new InvalidOperationException($"Invalid Vdup size \"{op.Size}\"."),
|
||||
};
|
||||
|
||||
InsertScalar(context, op.Vd, insert);
|
||||
|
@ -1654,7 +1653,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
IOpCode32Simd op = (IOpCode32Simd)context.CurrOp;
|
||||
|
||||
Func<Operand, Operand, Operand> genericEmit = (n, m) =>
|
||||
Operand genericEmit(Operand n, Operand m)
|
||||
{
|
||||
Operand nNum = context.Copy(n);
|
||||
Operand mNum = context.Copy(m);
|
||||
|
@ -1688,7 +1687,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
return context.AddIntrinsic(isMaxNum ? Intrinsic.X86Maxpd : Intrinsic.X86Minpd, nNum, mNum);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (scalar)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -493,7 +492,7 @@ namespace ARMeilleure.Instructions
|
|||
OpCodeSimdFcond op = (OpCodeSimdFcond)context.CurrOp;
|
||||
|
||||
Operand lblTrue = Label();
|
||||
Operand lblEnd = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
||||
context.BranchIfTrue(lblTrue, InstEmitFlowHelper.GetCondTrue(context, op.Cond));
|
||||
|
||||
|
@ -510,7 +509,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
private static void EmitSetNzcv(ArmEmitterContext context, int nzcv)
|
||||
{
|
||||
Operand Extract(int value, int bit)
|
||||
static Operand Extract(int value, int bit)
|
||||
{
|
||||
if (bit != 0)
|
||||
{
|
||||
|
@ -532,7 +531,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
bool cmpWithZero = !(op is OpCodeSimdFcond) ? op.Bit3 : false;
|
||||
bool cmpWithZero = op is not OpCodeSimdFcond && op.Bit3;
|
||||
|
||||
if (Optimizations.FastFP && (signalNaNs ? Optimizations.UseAvx : Optimizations.UseSse2))
|
||||
{
|
||||
|
|
|
@ -5,7 +5,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -67,8 +66,8 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Vcvtps2ph, n, Const(X86GetRoundControl(FPRoundingMode.ToNearest)));
|
||||
res = context.AddIntrinsic(Intrinsic.X86Pslldq, res, Const(14)); // VectorZeroUpper112()
|
||||
res = context.AddIntrinsic(Intrinsic.X86Psrldq, res, Const(14));
|
||||
res = context.AddIntrinsic(Intrinsic.X86Pslldq, res, Const(14)); // VectorZeroUpper112()
|
||||
res = context.AddIntrinsic(Intrinsic.X86Psrldq, res, Const(14));
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -92,7 +91,7 @@ namespace ARMeilleure.Instructions
|
|||
Debug.Assert(!Optimizations.ForceLegacySse);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Vcvtph2ps, GetVec(op.Rn));
|
||||
res = context.VectorZeroUpper96(res);
|
||||
res = context.VectorZeroUpper96(res);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -116,7 +115,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Cvtsd2ss, context.VectorZero(), n);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Vcvtps2ph, res, Const(X86GetRoundControl(FPRoundingMode.ToNearest)));
|
||||
res = context.AddIntrinsic(Intrinsic.X86Vcvtps2ph, res, Const(X86GetRoundControl(FPRoundingMode.ToNearest)));
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -140,8 +139,8 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Vcvtph2ps, GetVec(op.Rn));
|
||||
res = context.AddIntrinsic(Intrinsic.X86Cvtss2sd, context.VectorZero(), res);
|
||||
res = context.VectorZeroUpper64(res);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Cvtss2sd, context.VectorZero(), res);
|
||||
res = context.VectorZeroUpper64(res);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -273,7 +272,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Operand res = op.RegisterSize == RegisterSize.Simd128 ? context.AddIntrinsic(Intrinsic.X86Movhlps, n, n) : n;
|
||||
res = context.AddIntrinsic(Intrinsic.X86Cvtps2pd, res);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Cvtps2pd, res);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -284,7 +283,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Operand res = op.RegisterSize == RegisterSize.Simd128 ? context.AddIntrinsic(Intrinsic.X86Movhlps, n, n) : n;
|
||||
res = context.AddIntrinsic(Intrinsic.X86Vcvtph2ps, res);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Vcvtph2ps, res);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -387,10 +386,10 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic movInst = op.RegisterSize == RegisterSize.Simd128 ? Intrinsic.X86Movlhps : Intrinsic.X86Movhlps;
|
||||
|
||||
Operand nInt = context.AddIntrinsic(Intrinsic.X86Cvtpd2ps, GetVec(op.Rn));
|
||||
nInt = context.AddIntrinsic(Intrinsic.X86Movlhps, nInt, nInt);
|
||||
nInt = context.AddIntrinsic(Intrinsic.X86Movlhps, nInt, nInt);
|
||||
|
||||
Operand res = context.VectorZeroUpper64(d);
|
||||
res = context.AddIntrinsic(movInst, res, nInt);
|
||||
res = context.AddIntrinsic(movInst, res, nInt);
|
||||
|
||||
context.Copy(d, res);
|
||||
}
|
||||
|
@ -404,10 +403,10 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic movInst = op.RegisterSize == RegisterSize.Simd128 ? Intrinsic.X86Movlhps : Intrinsic.X86Movhlps;
|
||||
|
||||
Operand nInt = context.AddIntrinsic(Intrinsic.X86Vcvtps2ph, n, Const(X86GetRoundControl(FPRoundingMode.ToNearest)));
|
||||
nInt = context.AddIntrinsic(Intrinsic.X86Movlhps, nInt, nInt);
|
||||
nInt = context.AddIntrinsic(Intrinsic.X86Movlhps, nInt, nInt);
|
||||
|
||||
Operand res = context.VectorZeroUpper64(d);
|
||||
res = context.AddIntrinsic(movInst, res, nInt);
|
||||
res = context.AddIntrinsic(movInst, res, nInt);
|
||||
|
||||
context.Copy(d, res);
|
||||
}
|
||||
|
@ -1225,15 +1224,15 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Debug.Assert(opF.Type == OperandType.V128);
|
||||
|
||||
Operand longL = context.AddIntrinsicLong (Intrinsic.X86Cvtsd2si, opF); // opFL
|
||||
Operand res = context.VectorCreateScalar(longL);
|
||||
Operand longL = context.AddIntrinsicLong(Intrinsic.X86Cvtsd2si, opF); // opFL
|
||||
Operand res = context.VectorCreateScalar(longL);
|
||||
|
||||
if (!scalar)
|
||||
{
|
||||
Operand opFH = context.AddIntrinsic (Intrinsic.X86Movhlps, res, opF); // res doesn't matter.
|
||||
Operand longH = context.AddIntrinsicLong (Intrinsic.X86Cvtsd2si, opFH);
|
||||
Operand resH = context.VectorCreateScalar(longH);
|
||||
res = context.AddIntrinsic (Intrinsic.X86Movlhps, res, resH);
|
||||
Operand opFH = context.AddIntrinsic(Intrinsic.X86Movhlps, res, opF); // res doesn't matter.
|
||||
Operand longH = context.AddIntrinsicLong(Intrinsic.X86Cvtsd2si, opFH);
|
||||
Operand resH = context.VectorCreateScalar(longH);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Movlhps, res, resH);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -1244,14 +1243,14 @@ namespace ARMeilleure.Instructions
|
|||
Debug.Assert(op.Type == OperandType.V128);
|
||||
|
||||
Operand longL = context.AddIntrinsicLong(Intrinsic.X86Cvtsi2si, op); // opL
|
||||
Operand res = context.AddIntrinsic (Intrinsic.X86Cvtsi2sd, context.VectorZero(), longL);
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Cvtsi2sd, context.VectorZero(), longL);
|
||||
|
||||
if (!scalar)
|
||||
{
|
||||
Operand opH = context.AddIntrinsic (Intrinsic.X86Movhlps, res, op); // res doesn't matter.
|
||||
Operand opH = context.AddIntrinsic(Intrinsic.X86Movhlps, res, op); // res doesn't matter.
|
||||
Operand longH = context.AddIntrinsicLong(Intrinsic.X86Cvtsi2si, opH);
|
||||
Operand resH = context.AddIntrinsic (Intrinsic.X86Cvtsi2sd, res, longH); // res doesn't matter.
|
||||
res = context.AddIntrinsic (Intrinsic.X86Movlhps, res, resH);
|
||||
Operand resH = context.AddIntrinsic(Intrinsic.X86Cvtsi2sd, res, longH); // res doesn't matter.
|
||||
res = context.AddIntrinsic(Intrinsic.X86Movlhps, res, resH);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -1278,7 +1277,7 @@ namespace ARMeilleure.Instructions
|
|||
int fpScaled = 0x3F800000 - fBits * 0x800000;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulps, res, fpScaledMask);
|
||||
|
@ -1307,7 +1306,7 @@ namespace ARMeilleure.Instructions
|
|||
long fpScaled = 0x3FF0000000000000L - fBits * 0x10000000000000L;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulpd, res, fpScaledMask);
|
||||
|
@ -1334,16 +1333,16 @@ namespace ARMeilleure.Instructions
|
|||
if (sizeF == 0)
|
||||
{
|
||||
Operand mask = scalar // 65536.000f (1 << 16)
|
||||
? X86GetScalar (context, 0x47800000)
|
||||
? X86GetScalar(context, 0x47800000)
|
||||
: X86GetAllElements(context, 0x47800000);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Psrld, n, Const(16));
|
||||
res = context.AddIntrinsic(Intrinsic.X86Cvtdq2ps, res);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulps, res, mask);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Cvtdq2ps, res);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulps, res, mask);
|
||||
|
||||
Operand res2 = context.AddIntrinsic(Intrinsic.X86Pslld, n, Const(16));
|
||||
res2 = context.AddIntrinsic(Intrinsic.X86Psrld, res2, Const(16));
|
||||
res2 = context.AddIntrinsic(Intrinsic.X86Cvtdq2ps, res2);
|
||||
res2 = context.AddIntrinsic(Intrinsic.X86Psrld, res2, Const(16));
|
||||
res2 = context.AddIntrinsic(Intrinsic.X86Cvtdq2ps, res2);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Addps, res, res2);
|
||||
|
||||
|
@ -1355,7 +1354,7 @@ namespace ARMeilleure.Instructions
|
|||
int fpScaled = 0x3F800000 - fBits * 0x800000;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulps, res, fpScaledMask);
|
||||
|
@ -1375,16 +1374,16 @@ namespace ARMeilleure.Instructions
|
|||
else /* if (sizeF == 1) */
|
||||
{
|
||||
Operand mask = scalar // 4294967296.0000000d (1L << 32)
|
||||
? X86GetScalar (context, 0x41F0000000000000L)
|
||||
? X86GetScalar(context, 0x41F0000000000000L)
|
||||
: X86GetAllElements(context, 0x41F0000000000000L);
|
||||
|
||||
Operand res = context.AddIntrinsic (Intrinsic.X86Psrlq, n, Const(32));
|
||||
res = EmitSse2CvtInt64ToDoubleOp(context, res, scalar);
|
||||
res = context.AddIntrinsic (Intrinsic.X86Mulpd, res, mask);
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Psrlq, n, Const(32));
|
||||
res = EmitSse2CvtInt64ToDoubleOp(context, res, scalar);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulpd, res, mask);
|
||||
|
||||
Operand res2 = context.AddIntrinsic (Intrinsic.X86Psllq, n, Const(32));
|
||||
res2 = context.AddIntrinsic (Intrinsic.X86Psrlq, res2, Const(32));
|
||||
res2 = EmitSse2CvtInt64ToDoubleOp(context, res2, scalar);
|
||||
Operand res2 = context.AddIntrinsic(Intrinsic.X86Psllq, n, Const(32));
|
||||
res2 = context.AddIntrinsic(Intrinsic.X86Psrlq, res2, Const(32));
|
||||
res2 = EmitSse2CvtInt64ToDoubleOp(context, res2, scalar);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Addpd, res, res2);
|
||||
|
||||
|
@ -1396,7 +1395,7 @@ namespace ARMeilleure.Instructions
|
|||
long fpScaled = 0x3FF0000000000000L - fBits * 0x10000000000000L;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulpd, res, fpScaledMask);
|
||||
|
@ -1423,7 +1422,7 @@ namespace ARMeilleure.Instructions
|
|||
if (sizeF == 0)
|
||||
{
|
||||
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpps, n, n, Const((int)CmpCondition.OrderedQ));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
|
||||
if (op is OpCodeSimdShImm fixedOp)
|
||||
{
|
||||
|
@ -1433,7 +1432,7 @@ namespace ARMeilleure.Instructions
|
|||
int fpScaled = 0x3F800000 + fBits * 0x800000;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulps, nRes, fpScaledMask);
|
||||
|
@ -1451,7 +1450,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand nInt = context.AddIntrinsic(Intrinsic.X86Cvtps2dq, nRes);
|
||||
|
||||
Operand fpMaxValMask = scalar // 2.14748365E9f (2147483648)
|
||||
? X86GetScalar (context, 0x4F000000)
|
||||
? X86GetScalar(context, 0x4F000000)
|
||||
: X86GetAllElements(context, 0x4F000000);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Cmpps, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
|
||||
|
@ -1472,7 +1471,7 @@ namespace ARMeilleure.Instructions
|
|||
else /* if (sizeF == 1) */
|
||||
{
|
||||
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmppd, n, n, Const((int)CmpCondition.OrderedQ));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
|
||||
if (op is OpCodeSimdShImm fixedOp)
|
||||
{
|
||||
|
@ -1482,7 +1481,7 @@ namespace ARMeilleure.Instructions
|
|||
long fpScaled = 0x3FF0000000000000L + fBits * 0x10000000000000L;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulpd, nRes, fpScaledMask);
|
||||
|
@ -1500,7 +1499,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand nLong = EmitSse2CvtDoubleToInt64OpF(context, nRes, scalar);
|
||||
|
||||
Operand fpMaxValMask = scalar // 9.2233720368547760E18d (9223372036854775808)
|
||||
? X86GetScalar (context, 0x43E0000000000000L)
|
||||
? X86GetScalar(context, 0x43E0000000000000L)
|
||||
: X86GetAllElements(context, 0x43E0000000000000L);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Cmppd, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
|
||||
|
@ -1528,7 +1527,7 @@ namespace ARMeilleure.Instructions
|
|||
if (sizeF == 0)
|
||||
{
|
||||
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpps, n, n, Const((int)CmpCondition.OrderedQ));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
|
||||
if (op is OpCodeSimdShImm fixedOp)
|
||||
{
|
||||
|
@ -1538,7 +1537,7 @@ namespace ARMeilleure.Instructions
|
|||
int fpScaled = 0x3F800000 + fBits * 0x800000;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulps, nRes, fpScaledMask);
|
||||
|
@ -1556,10 +1555,10 @@ namespace ARMeilleure.Instructions
|
|||
Operand zero = context.VectorZero();
|
||||
|
||||
Operand nCmp = context.AddIntrinsic(Intrinsic.X86Cmpps, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
|
||||
Operand fpMaxValMask = scalar // 2.14748365E9f (2147483648)
|
||||
? X86GetScalar (context, 0x4F000000)
|
||||
? X86GetScalar(context, 0x4F000000)
|
||||
: X86GetAllElements(context, 0x4F000000);
|
||||
|
||||
Operand nInt = context.AddIntrinsic(Intrinsic.X86Cvtps2dq, nRes);
|
||||
|
@ -1567,14 +1566,14 @@ namespace ARMeilleure.Instructions
|
|||
nRes = context.AddIntrinsic(Intrinsic.X86Subps, nRes, fpMaxValMask);
|
||||
|
||||
nCmp = context.AddIntrinsic(Intrinsic.X86Cmpps, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
|
||||
Operand nInt2 = context.AddIntrinsic(Intrinsic.X86Cvtps2dq, nRes);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Cmpps, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
|
||||
|
||||
Operand dRes = context.AddIntrinsic(Intrinsic.X86Pxor, nInt2, nRes);
|
||||
dRes = context.AddIntrinsic(Intrinsic.X86Paddd, dRes, nInt);
|
||||
Operand dRes = context.AddIntrinsic(Intrinsic.X86Pxor, nInt2, nRes);
|
||||
dRes = context.AddIntrinsic(Intrinsic.X86Paddd, dRes, nInt);
|
||||
|
||||
if (scalar)
|
||||
{
|
||||
|
@ -1590,7 +1589,7 @@ namespace ARMeilleure.Instructions
|
|||
else /* if (sizeF == 1) */
|
||||
{
|
||||
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmppd, n, n, Const((int)CmpCondition.OrderedQ));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
|
||||
if (op is OpCodeSimdShImm fixedOp)
|
||||
{
|
||||
|
@ -1600,7 +1599,7 @@ namespace ARMeilleure.Instructions
|
|||
long fpScaled = 0x3FF0000000000000L + fBits * 0x10000000000000L;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulpd, nRes, fpScaledMask);
|
||||
|
@ -1618,10 +1617,10 @@ namespace ARMeilleure.Instructions
|
|||
Operand zero = context.VectorZero();
|
||||
|
||||
Operand nCmp = context.AddIntrinsic(Intrinsic.X86Cmppd, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
|
||||
Operand fpMaxValMask = scalar // 9.2233720368547760E18d (9223372036854775808)
|
||||
? X86GetScalar (context, 0x43E0000000000000L)
|
||||
? X86GetScalar(context, 0x43E0000000000000L)
|
||||
: X86GetAllElements(context, 0x43E0000000000000L);
|
||||
|
||||
Operand nLong = EmitSse2CvtDoubleToInt64OpF(context, nRes, scalar);
|
||||
|
@ -1629,14 +1628,14 @@ namespace ARMeilleure.Instructions
|
|||
nRes = context.AddIntrinsic(Intrinsic.X86Subpd, nRes, fpMaxValMask);
|
||||
|
||||
nCmp = context.AddIntrinsic(Intrinsic.X86Cmppd, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
|
||||
Operand nLong2 = EmitSse2CvtDoubleToInt64OpF(context, nRes, scalar);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Cmppd, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
|
||||
|
||||
Operand dRes = context.AddIntrinsic(Intrinsic.X86Pxor, nLong2, nRes);
|
||||
dRes = context.AddIntrinsic(Intrinsic.X86Paddq, dRes, nLong);
|
||||
Operand dRes = context.AddIntrinsic(Intrinsic.X86Pxor, nLong2, nRes);
|
||||
dRes = context.AddIntrinsic(Intrinsic.X86Paddq, dRes, nLong);
|
||||
|
||||
if (scalar)
|
||||
{
|
||||
|
@ -1656,7 +1655,7 @@ namespace ARMeilleure.Instructions
|
|||
if (op.Size == 0)
|
||||
{
|
||||
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpss, n, n, Const((int)CmpCondition.OrderedQ));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
|
||||
if (isFixed)
|
||||
{
|
||||
|
@ -1678,7 +1677,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
Operand nIntOrLong = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtss2si, nRes)
|
||||
? context.AddIntrinsicInt(Intrinsic.X86Cvtss2si, nRes)
|
||||
: context.AddIntrinsicLong(Intrinsic.X86Cvtss2si, nRes);
|
||||
|
||||
int fpMaxVal = op.RegisterSize == RegisterSize.Int32
|
||||
|
@ -1703,7 +1702,7 @@ namespace ARMeilleure.Instructions
|
|||
else /* if (op.Size == 1) */
|
||||
{
|
||||
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpsd, n, n, Const((int)CmpCondition.OrderedQ));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
|
||||
if (isFixed)
|
||||
{
|
||||
|
@ -1725,7 +1724,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
Operand nIntOrLong = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtsd2si, nRes)
|
||||
? context.AddIntrinsicInt(Intrinsic.X86Cvtsd2si, nRes)
|
||||
: context.AddIntrinsicLong(Intrinsic.X86Cvtsd2si, nRes);
|
||||
|
||||
long fpMaxVal = op.RegisterSize == RegisterSize.Int32
|
||||
|
@ -1758,7 +1757,7 @@ namespace ARMeilleure.Instructions
|
|||
if (op.Size == 0)
|
||||
{
|
||||
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpss, n, n, Const((int)CmpCondition.OrderedQ));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
|
||||
if (isFixed)
|
||||
{
|
||||
|
@ -1782,7 +1781,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand zero = context.VectorZero();
|
||||
|
||||
Operand nCmp = context.AddIntrinsic(Intrinsic.X86Cmpss, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
|
||||
int fpMaxVal = op.RegisterSize == RegisterSize.Int32
|
||||
? 0x4F000000 // 2.14748365E9f (2147483648)
|
||||
|
@ -1791,16 +1790,16 @@ namespace ARMeilleure.Instructions
|
|||
Operand fpMaxValMask = X86GetScalar(context, fpMaxVal);
|
||||
|
||||
Operand nIntOrLong = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtss2si, nRes)
|
||||
? context.AddIntrinsicInt(Intrinsic.X86Cvtss2si, nRes)
|
||||
: context.AddIntrinsicLong(Intrinsic.X86Cvtss2si, nRes);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Subss, nRes, fpMaxValMask);
|
||||
|
||||
nCmp = context.AddIntrinsic(Intrinsic.X86Cmpss, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
|
||||
Operand nIntOrLong2 = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtss2si, nRes)
|
||||
? context.AddIntrinsicInt(Intrinsic.X86Cvtss2si, nRes)
|
||||
: context.AddIntrinsicLong(Intrinsic.X86Cvtss2si, nRes);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Cmpss, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
|
||||
|
@ -1813,14 +1812,14 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
Operand dRes = context.BitwiseExclusiveOr(nIntOrLong2, nInt);
|
||||
dRes = context.Add(dRes, nIntOrLong);
|
||||
dRes = context.Add(dRes, nIntOrLong);
|
||||
|
||||
SetIntOrZR(context, op.Rd, dRes);
|
||||
}
|
||||
else /* if (op.Size == 1) */
|
||||
{
|
||||
Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpsd, n, n, Const((int)CmpCondition.OrderedQ));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n);
|
||||
|
||||
if (isFixed)
|
||||
{
|
||||
|
@ -1844,7 +1843,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand zero = context.VectorZero();
|
||||
|
||||
Operand nCmp = context.AddIntrinsic(Intrinsic.X86Cmpsd, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
|
||||
long fpMaxVal = op.RegisterSize == RegisterSize.Int32
|
||||
? 0x41E0000000000000L // 2147483648.0000000d (2147483648)
|
||||
|
@ -1853,16 +1852,16 @@ namespace ARMeilleure.Instructions
|
|||
Operand fpMaxValMask = X86GetScalar(context, fpMaxVal);
|
||||
|
||||
Operand nIntOrLong = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtsd2si, nRes)
|
||||
? context.AddIntrinsicInt(Intrinsic.X86Cvtsd2si, nRes)
|
||||
: context.AddIntrinsicLong(Intrinsic.X86Cvtsd2si, nRes);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Subsd, nRes, fpMaxValMask);
|
||||
|
||||
nCmp = context.AddIntrinsic(Intrinsic.X86Cmpsd, nRes, zero, Const((int)CmpCondition.NotLessThanOrEqual));
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
|
||||
Operand nIntOrLong2 = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtsd2si, nRes)
|
||||
? context.AddIntrinsicInt(Intrinsic.X86Cvtsd2si, nRes)
|
||||
: context.AddIntrinsicLong(Intrinsic.X86Cvtsd2si, nRes);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Cmpsd, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
|
||||
|
@ -1875,7 +1874,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
Operand dRes = context.BitwiseExclusiveOr(nIntOrLong2, nLong);
|
||||
dRes = context.Add(dRes, nIntOrLong);
|
||||
dRes = context.Add(dRes, nIntOrLong);
|
||||
|
||||
SetIntOrZR(context, op.Rd, dRes);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
|
||||
|
@ -217,33 +216,22 @@ namespace ARMeilleure.Instructions
|
|||
string name = nameof(Math.Round);
|
||||
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(MidpointRounding) })
|
||||
: typeof(Math). GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(MidpointRounding) })
|
||||
: typeof(Math).GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
|
||||
|
||||
return context.Call(info, n, Const((int)roundMode));
|
||||
}
|
||||
|
||||
private static FPRoundingMode RMToRoundMode(int rm)
|
||||
{
|
||||
FPRoundingMode roundMode;
|
||||
switch (rm)
|
||||
return rm switch
|
||||
{
|
||||
case 0b00:
|
||||
roundMode = FPRoundingMode.ToNearestAway;
|
||||
break;
|
||||
case 0b01:
|
||||
roundMode = FPRoundingMode.ToNearest;
|
||||
break;
|
||||
case 0b10:
|
||||
roundMode = FPRoundingMode.TowardsPlusInfinity;
|
||||
break;
|
||||
case 0b11:
|
||||
roundMode = FPRoundingMode.TowardsMinusInfinity;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(rm));
|
||||
}
|
||||
return roundMode;
|
||||
0b00 => FPRoundingMode.ToNearestAway,
|
||||
0b01 => FPRoundingMode.ToNearest,
|
||||
0b10 => FPRoundingMode.TowardsPlusInfinity,
|
||||
0b11 => FPRoundingMode.TowardsMinusInfinity,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm)),
|
||||
};
|
||||
}
|
||||
|
||||
// VCVTA/M/N/P (floating-point).
|
||||
|
@ -270,22 +258,24 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (unsigned)
|
||||
{
|
||||
inst = rm switch {
|
||||
inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FcvtauGp,
|
||||
0b01 => Intrinsic.Arm64FcvtnuGp,
|
||||
0b10 => Intrinsic.Arm64FcvtpuGp,
|
||||
0b11 => Intrinsic.Arm64FcvtmuGp,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
inst = rm switch {
|
||||
inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FcvtasGp,
|
||||
0b01 => Intrinsic.Arm64FcvtnsGp,
|
||||
0b10 => Intrinsic.Arm64FcvtpsGp,
|
||||
0b11 => Intrinsic.Arm64FcvtmsGp,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -297,22 +287,24 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (unsigned)
|
||||
{
|
||||
inst = rm switch {
|
||||
inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FcvtauS,
|
||||
0b01 => Intrinsic.Arm64FcvtnuS,
|
||||
0b10 => Intrinsic.Arm64FcvtpuS,
|
||||
0b11 => Intrinsic.Arm64FcvtmuS,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
inst = rm switch {
|
||||
inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FcvtasS,
|
||||
0b01 => Intrinsic.Arm64FcvtnsS,
|
||||
0b10 => Intrinsic.Arm64FcvtpsS,
|
||||
0b11 => Intrinsic.Arm64FcvtmsS,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -432,12 +424,13 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
Intrinsic inst = rm switch {
|
||||
Intrinsic inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FrintaS,
|
||||
0b01 => Intrinsic.Arm64FrintnS,
|
||||
0b10 => Intrinsic.Arm64FrintpS,
|
||||
0b11 => Intrinsic.Arm64FrintmS,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
|
||||
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, inst);
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
static partial class InstEmit
|
||||
{
|
||||
#region "Sha1"
|
||||
#region "Sha1"
|
||||
public static void Sha1c_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
@ -89,9 +89,9 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "Sha256"
|
||||
#region "Sha256"
|
||||
public static void Sha256h_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
@ -142,6 +142,6 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
static partial class InstEmit32
|
||||
{
|
||||
#region "Sha256"
|
||||
#region "Sha256"
|
||||
public static void Sha256h_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
|
||||
|
@ -59,6 +59,6 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
context.Copy(GetVecA32(op.Qd), res);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,9 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand round2 = context.AddIntrinsic(Intrinsic.X86Sha256Rnds2, src1, src2, w);
|
||||
Operand round4 = context.AddIntrinsic(Intrinsic.X86Sha256Rnds2, src2, round2, w2);
|
||||
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Shufps, round4, round2, Const(part2 ? 0x11 : 0xbb));
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -53,4 +53,4 @@ namespace ARMeilleure.Instructions
|
|||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)), x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -18,19 +17,19 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
static class InstEmitSimdHelper
|
||||
{
|
||||
#region "Masks"
|
||||
#region "Masks"
|
||||
public static readonly long[] EvenMasks = new long[]
|
||||
{
|
||||
14L << 56 | 12L << 48 | 10L << 40 | 08L << 32 | 06L << 24 | 04L << 16 | 02L << 8 | 00L << 0, // B
|
||||
13L << 56 | 12L << 48 | 09L << 40 | 08L << 32 | 05L << 24 | 04L << 16 | 01L << 8 | 00L << 0, // H
|
||||
11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 03L << 24 | 02L << 16 | 01L << 8 | 00L << 0 // S
|
||||
11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 03L << 24 | 02L << 16 | 01L << 8 | 00L << 0, // S
|
||||
};
|
||||
|
||||
public static readonly long[] OddMasks = new long[]
|
||||
{
|
||||
15L << 56 | 13L << 48 | 11L << 40 | 09L << 32 | 07L << 24 | 05L << 16 | 03L << 8 | 01L << 0, // B
|
||||
15L << 56 | 14L << 48 | 11L << 40 | 10L << 32 | 07L << 24 | 06L << 16 | 03L << 8 | 02L << 0, // H
|
||||
15L << 56 | 14L << 48 | 13L << 40 | 12L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0 // S
|
||||
15L << 56 | 14L << 48 | 13L << 40 | 12L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0, // S
|
||||
};
|
||||
|
||||
public static readonly long ZeroMask = 128L << 56 | 128L << 48 | 128L << 40 | 128L << 32 | 128L << 24 | 128L << 16 | 128L << 8 | 128L << 0;
|
||||
|
@ -38,19 +37,19 @@ namespace ARMeilleure.Instructions
|
|||
public static ulong X86GetGf2p8LogicalShiftLeft(int shift)
|
||||
{
|
||||
ulong identity = (0b00000001UL << 56) | (0b00000010UL << 48) | (0b00000100UL << 40) | (0b00001000UL << 32) |
|
||||
(0b00010000UL << 24) | (0b00100000UL << 16) | (0b01000000UL << 8) | (0b10000000UL << 0);
|
||||
(0b00010000UL << 24) | (0b00100000UL << 16) | (0b01000000UL << 8) | (0b10000000UL << 0);
|
||||
|
||||
return shift >= 0 ? identity >> (shift * 8) : identity << (-shift * 8);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "X86 SSE Intrinsics"
|
||||
#region "X86 SSE Intrinsics"
|
||||
public static readonly Intrinsic[] X86PaddInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Paddb,
|
||||
Intrinsic.X86Paddw,
|
||||
Intrinsic.X86Paddd,
|
||||
Intrinsic.X86Paddq
|
||||
Intrinsic.X86Paddq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PcmpeqInstruction = new Intrinsic[]
|
||||
|
@ -58,7 +57,7 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Pcmpeqb,
|
||||
Intrinsic.X86Pcmpeqw,
|
||||
Intrinsic.X86Pcmpeqd,
|
||||
Intrinsic.X86Pcmpeqq
|
||||
Intrinsic.X86Pcmpeqq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PcmpgtInstruction = new Intrinsic[]
|
||||
|
@ -66,49 +65,49 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Pcmpgtb,
|
||||
Intrinsic.X86Pcmpgtw,
|
||||
Intrinsic.X86Pcmpgtd,
|
||||
Intrinsic.X86Pcmpgtq
|
||||
Intrinsic.X86Pcmpgtq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PmaxsInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pmaxsb,
|
||||
Intrinsic.X86Pmaxsw,
|
||||
Intrinsic.X86Pmaxsd
|
||||
Intrinsic.X86Pmaxsd,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PmaxuInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pmaxub,
|
||||
Intrinsic.X86Pmaxuw,
|
||||
Intrinsic.X86Pmaxud
|
||||
Intrinsic.X86Pmaxud,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PminsInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pminsb,
|
||||
Intrinsic.X86Pminsw,
|
||||
Intrinsic.X86Pminsd
|
||||
Intrinsic.X86Pminsd,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PminuInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pminub,
|
||||
Intrinsic.X86Pminuw,
|
||||
Intrinsic.X86Pminud
|
||||
Intrinsic.X86Pminud,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PmovsxInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pmovsxbw,
|
||||
Intrinsic.X86Pmovsxwd,
|
||||
Intrinsic.X86Pmovsxdq
|
||||
Intrinsic.X86Pmovsxdq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PmovzxInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pmovzxbw,
|
||||
Intrinsic.X86Pmovzxwd,
|
||||
Intrinsic.X86Pmovzxdq
|
||||
Intrinsic.X86Pmovzxdq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PsllInstruction = new Intrinsic[]
|
||||
|
@ -116,14 +115,14 @@ namespace ARMeilleure.Instructions
|
|||
0,
|
||||
Intrinsic.X86Psllw,
|
||||
Intrinsic.X86Pslld,
|
||||
Intrinsic.X86Psllq
|
||||
Intrinsic.X86Psllq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PsraInstruction = new Intrinsic[]
|
||||
{
|
||||
0,
|
||||
Intrinsic.X86Psraw,
|
||||
Intrinsic.X86Psrad
|
||||
Intrinsic.X86Psrad,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PsrlInstruction = new Intrinsic[]
|
||||
|
@ -131,7 +130,7 @@ namespace ARMeilleure.Instructions
|
|||
0,
|
||||
Intrinsic.X86Psrlw,
|
||||
Intrinsic.X86Psrld,
|
||||
Intrinsic.X86Psrlq
|
||||
Intrinsic.X86Psrlq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PsubInstruction = new Intrinsic[]
|
||||
|
@ -139,7 +138,7 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Psubb,
|
||||
Intrinsic.X86Psubw,
|
||||
Intrinsic.X86Psubd,
|
||||
Intrinsic.X86Psubq
|
||||
Intrinsic.X86Psubq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PunpckhInstruction = new Intrinsic[]
|
||||
|
@ -147,7 +146,7 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Punpckhbw,
|
||||
Intrinsic.X86Punpckhwd,
|
||||
Intrinsic.X86Punpckhdq,
|
||||
Intrinsic.X86Punpckhqdq
|
||||
Intrinsic.X86Punpckhqdq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PunpcklInstruction = new Intrinsic[]
|
||||
|
@ -155,9 +154,9 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Punpcklbw,
|
||||
Intrinsic.X86Punpcklwd,
|
||||
Intrinsic.X86Punpckldq,
|
||||
Intrinsic.X86Punpcklqdq
|
||||
Intrinsic.X86Punpcklqdq,
|
||||
};
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
public static void EnterArmFpMode(EmitterContext context, Func<FPState, Operand> getFpFlag)
|
||||
{
|
||||
|
@ -310,15 +309,16 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static int X86GetRoundControl(FPRoundingMode roundMode)
|
||||
{
|
||||
switch (roundMode)
|
||||
return roundMode switch
|
||||
{
|
||||
case FPRoundingMode.ToNearest: return 8 | 0; // even
|
||||
case FPRoundingMode.TowardsPlusInfinity: return 8 | 2;
|
||||
case FPRoundingMode.TowardsMinusInfinity: return 8 | 1;
|
||||
case FPRoundingMode.TowardsZero: return 8 | 3;
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Invalid rounding mode \"{roundMode}\".");
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
FPRoundingMode.ToNearest => 8 | 0, // even
|
||||
FPRoundingMode.TowardsPlusInfinity => 8 | 2,
|
||||
FPRoundingMode.TowardsMinusInfinity => 8 | 1,
|
||||
FPRoundingMode.TowardsZero => 8 | 3,
|
||||
_ => throw new ArgumentException($"Invalid rounding mode \"{roundMode}\"."),
|
||||
#pragma warning restore IDE0055
|
||||
};
|
||||
}
|
||||
|
||||
public static Operand EmitSse41RoundToNearestWithTiesToAwayOpF(ArmEmitterContext context, Operand n, bool scalar)
|
||||
|
@ -334,11 +334,11 @@ namespace ARMeilleure.Instructions
|
|||
if ((op.Size & 1) == 0)
|
||||
{
|
||||
Operand signMask = scalar ? X86GetScalar(context, int.MinValue) : X86GetAllElements(context, int.MinValue);
|
||||
signMask = context.AddIntrinsic(Intrinsic.X86Pand, signMask, nCopy);
|
||||
signMask = context.AddIntrinsic(Intrinsic.X86Pand, signMask, nCopy);
|
||||
|
||||
// 0x3EFFFFFF == BitConverter.SingleToInt32Bits(0.5f) - 1
|
||||
Operand valueMask = scalar ? X86GetScalar(context, 0x3EFFFFFF) : X86GetAllElements(context, 0x3EFFFFFF);
|
||||
valueMask = context.AddIntrinsic(Intrinsic.X86Por, valueMask, signMask);
|
||||
valueMask = context.AddIntrinsic(Intrinsic.X86Por, valueMask, signMask);
|
||||
|
||||
nCopy = context.AddIntrinsic(scalar ? Intrinsic.X86Addss : Intrinsic.X86Addps, nCopy, valueMask);
|
||||
|
||||
|
@ -347,11 +347,11 @@ namespace ARMeilleure.Instructions
|
|||
else
|
||||
{
|
||||
Operand signMask = scalar ? X86GetScalar(context, long.MinValue) : X86GetAllElements(context, long.MinValue);
|
||||
signMask = context.AddIntrinsic(Intrinsic.X86Pand, signMask, nCopy);
|
||||
signMask = context.AddIntrinsic(Intrinsic.X86Pand, signMask, nCopy);
|
||||
|
||||
// 0x3FDFFFFFFFFFFFFFL == BitConverter.DoubleToInt64Bits(0.5d) - 1L
|
||||
Operand valueMask = scalar ? X86GetScalar(context, 0x3FDFFFFFFFFFFFFFL) : X86GetAllElements(context, 0x3FDFFFFFFFFFFFFFL);
|
||||
valueMask = context.AddIntrinsic(Intrinsic.X86Por, valueMask, signMask);
|
||||
valueMask = context.AddIntrinsic(Intrinsic.X86Por, valueMask, signMask);
|
||||
|
||||
nCopy = context.AddIntrinsic(scalar ? Intrinsic.X86Addsd : Intrinsic.X86Addpd, nCopy, valueMask);
|
||||
|
||||
|
@ -461,7 +461,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float) })
|
||||
: typeof(Math). GetMethod(name, new Type[] { typeof(double) });
|
||||
: typeof(Math).GetMethod(name, new Type[] { typeof(double) });
|
||||
|
||||
return context.Call(info, n);
|
||||
}
|
||||
|
@ -473,8 +473,8 @@ namespace ARMeilleure.Instructions
|
|||
string name = nameof(Math.Round);
|
||||
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(MidpointRounding) })
|
||||
: typeof(Math). GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(MidpointRounding) })
|
||||
: typeof(Math).GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
|
||||
|
||||
return context.Call(info, n, Const((int)roundMode));
|
||||
}
|
||||
|
@ -482,7 +482,7 @@ namespace ARMeilleure.Instructions
|
|||
public static Operand EmitGetRoundingMode(ArmEmitterContext context)
|
||||
{
|
||||
Operand rMode = context.ShiftLeft(GetFpFlag(FPState.RMode1Flag), Const(1));
|
||||
rMode = context.BitwiseOr(rMode, GetFpFlag(FPState.RMode0Flag));
|
||||
rMode = context.BitwiseOr(rMode, GetFpFlag(FPState.RMode0Flag));
|
||||
|
||||
return rMode;
|
||||
}
|
||||
|
@ -1015,8 +1015,8 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
for (int index = 0; index < elems; index++)
|
||||
{
|
||||
Operand ne = EmitVectorExtract(context, op.Rn, index, op.Size + 1, signed);
|
||||
Operand me = EmitVectorExtract(context, op.Rm, part + index, op.Size, signed);
|
||||
Operand ne = EmitVectorExtract(context, op.Rn, index, op.Size + 1, signed);
|
||||
Operand me = EmitVectorExtract(context, op.Rm, part + index, op.Size, signed);
|
||||
|
||||
res = EmitVectorInsert(context, res, emit(ne, me), index, op.Size + 1);
|
||||
}
|
||||
|
@ -1077,9 +1077,9 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
for (int index = 0; index < elems; index++)
|
||||
{
|
||||
Operand de = EmitVectorExtract(context, op.Rd, index, op.Size + 1, signed);
|
||||
Operand ne = EmitVectorExtract(context, op.Rn, part + index, op.Size, signed);
|
||||
Operand me = EmitVectorExtract(context, op.Rm, part + index, op.Size, signed);
|
||||
Operand de = EmitVectorExtract(context, op.Rd, index, op.Size + 1, signed);
|
||||
Operand ne = EmitVectorExtract(context, op.Rn, part + index, op.Size, signed);
|
||||
Operand me = EmitVectorExtract(context, op.Rm, part + index, op.Size, signed);
|
||||
|
||||
res = EmitVectorInsert(context, res, emit(de, ne, me), index, op.Size + 1);
|
||||
}
|
||||
|
@ -1143,8 +1143,8 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
for (int index = 0; index < elems; index++)
|
||||
{
|
||||
Operand de = EmitVectorExtract(context, op.Rd, index, op.Size + 1, signed);
|
||||
Operand ne = EmitVectorExtract(context, op.Rn, part + index, op.Size, signed);
|
||||
Operand de = EmitVectorExtract(context, op.Rd, index, op.Size + 1, signed);
|
||||
Operand ne = EmitVectorExtract(context, op.Rn, part + index, op.Size, signed);
|
||||
|
||||
res = EmitVectorInsert(context, res, emit(de, ne, me), index, op.Size + 1);
|
||||
}
|
||||
|
@ -1174,13 +1174,13 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
int pairIndex = index << 1;
|
||||
|
||||
Operand n0 = EmitVectorExtract(context, op.Rn, pairIndex, op.Size, signed);
|
||||
Operand n0 = EmitVectorExtract(context, op.Rn, pairIndex, op.Size, signed);
|
||||
Operand n1 = EmitVectorExtract(context, op.Rn, pairIndex + 1, op.Size, signed);
|
||||
|
||||
Operand m0 = EmitVectorExtract(context, op.Rm, pairIndex, op.Size, signed);
|
||||
Operand m0 = EmitVectorExtract(context, op.Rm, pairIndex, op.Size, signed);
|
||||
Operand m1 = EmitVectorExtract(context, op.Rm, pairIndex + 1, op.Size, signed);
|
||||
|
||||
res = EmitVectorInsert(context, res, emit(n0, n1), index, op.Size);
|
||||
res = EmitVectorInsert(context, res, emit(n0, n1), index, op.Size);
|
||||
res = EmitVectorInsert(context, res, emit(m0, m1), pairs + index, op.Size);
|
||||
}
|
||||
|
||||
|
@ -1197,11 +1197,11 @@ namespace ARMeilleure.Instructions
|
|||
if (op.RegisterSize == RegisterSize.Simd64)
|
||||
{
|
||||
Operand zeroEvenMask = X86GetElements(context, ZeroMask, EvenMasks[op.Size]);
|
||||
Operand zeroOddMask = X86GetElements(context, ZeroMask, OddMasks [op.Size]);
|
||||
Operand zeroOddMask = X86GetElements(context, ZeroMask, OddMasks[op.Size]);
|
||||
|
||||
Operand mN = context.AddIntrinsic(Intrinsic.X86Punpcklqdq, n, m); // m:n
|
||||
|
||||
Operand left = context.AddIntrinsic(Intrinsic.X86Pshufb, mN, zeroEvenMask); // 0:even from m:n
|
||||
Operand left = context.AddIntrinsic(Intrinsic.X86Pshufb, mN, zeroEvenMask); // 0:even from m:n
|
||||
Operand right = context.AddIntrinsic(Intrinsic.X86Pshufb, mN, zeroOddMask); // 0:odd from m:n
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst[op.Size], left, right));
|
||||
|
@ -1213,14 +1213,14 @@ namespace ARMeilleure.Instructions
|
|||
Operand oddEvenN = context.AddIntrinsic(Intrinsic.X86Pshufb, n, oddEvenMask); // odd:even from n
|
||||
Operand oddEvenM = context.AddIntrinsic(Intrinsic.X86Pshufb, m, oddEvenMask); // odd:even from m
|
||||
|
||||
Operand left = context.AddIntrinsic(Intrinsic.X86Punpcklqdq, oddEvenN, oddEvenM);
|
||||
Operand left = context.AddIntrinsic(Intrinsic.X86Punpcklqdq, oddEvenN, oddEvenM);
|
||||
Operand right = context.AddIntrinsic(Intrinsic.X86Punpckhqdq, oddEvenN, oddEvenM);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst[op.Size], left, right));
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand left = context.AddIntrinsic(Intrinsic.X86Punpcklqdq, n, m);
|
||||
Operand left = context.AddIntrinsic(Intrinsic.X86Punpcklqdq, n, m);
|
||||
Operand right = context.AddIntrinsic(Intrinsic.X86Punpckhqdq, n, m);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.AddIntrinsic(inst[3], left, right));
|
||||
|
@ -1381,7 +1381,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand m0 = context.VectorExtract(type, GetVec(op.Rm), pairIndex);
|
||||
Operand m1 = context.VectorExtract(type, GetVec(op.Rm), pairIndex + 1);
|
||||
|
||||
res = context.VectorInsert(res, emit(n0, n1), index);
|
||||
res = context.VectorInsert(res, emit(n0, n1), index);
|
||||
res = context.VectorInsert(res, emit(m0, m1), pairs + index);
|
||||
}
|
||||
|
||||
|
@ -1433,18 +1433,18 @@ namespace ARMeilleure.Instructions
|
|||
public enum CmpCondition
|
||||
{
|
||||
// Legacy Sse.
|
||||
Equal = 0, // Ordered, non-signaling.
|
||||
LessThan = 1, // Ordered, signaling.
|
||||
LessThanOrEqual = 2, // Ordered, signaling.
|
||||
UnorderedQ = 3, // Non-signaling.
|
||||
NotLessThan = 5, // Unordered, signaling.
|
||||
Equal = 0, // Ordered, non-signaling.
|
||||
LessThan = 1, // Ordered, signaling.
|
||||
LessThanOrEqual = 2, // Ordered, signaling.
|
||||
UnorderedQ = 3, // Non-signaling.
|
||||
NotLessThan = 5, // Unordered, signaling.
|
||||
NotLessThanOrEqual = 6, // Unordered, signaling.
|
||||
OrderedQ = 7, // Non-signaling.
|
||||
OrderedQ = 7, // Non-signaling.
|
||||
|
||||
// Vex.
|
||||
GreaterThanOrEqual = 13, // Ordered, signaling.
|
||||
GreaterThan = 14, // Ordered, signaling.
|
||||
OrderedS = 23 // Signaling.
|
||||
GreaterThan = 14, // Ordered, signaling.
|
||||
OrderedS = 23, // Signaling.
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
@ -1459,7 +1459,7 @@ namespace ARMeilleure.Instructions
|
|||
Add = 1 << 3,
|
||||
Sub = 1 << 4,
|
||||
|
||||
Accumulate = 1 << 5
|
||||
Accumulate = 1 << 5,
|
||||
}
|
||||
|
||||
public static void EmitScalarSaturatingUnaryOpSx(ArmEmitterContext context, Func1I emit)
|
||||
|
@ -1579,7 +1579,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand de;
|
||||
Operand ne = EmitVectorExtract(context, op.Rn, index, op.Size, !signed);
|
||||
Operand me = EmitVectorExtract(context, op.Rd, index, op.Size, signed);
|
||||
Operand me = EmitVectorExtract(context, op.Rd, index, op.Size, signed);
|
||||
|
||||
if (op.Size <= 2)
|
||||
{
|
||||
|
@ -1627,7 +1627,7 @@ namespace ARMeilleure.Instructions
|
|||
[Flags]
|
||||
public enum SaturatingNarrowFlags
|
||||
{
|
||||
Scalar = 1 << 0,
|
||||
Scalar = 1 << 0,
|
||||
SignedSrc = 1 << 1,
|
||||
SignedDst = 1 << 2,
|
||||
|
||||
|
@ -1637,14 +1637,14 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
VectorSxSx = SignedSrc | SignedDst,
|
||||
VectorSxZx = SignedSrc,
|
||||
VectorZxZx = 0
|
||||
VectorZxZx = 0,
|
||||
}
|
||||
|
||||
public static void EmitSaturatingNarrowOp(ArmEmitterContext context, SaturatingNarrowFlags flags)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
bool scalar = (flags & SaturatingNarrowFlags.Scalar) != 0;
|
||||
bool scalar = (flags & SaturatingNarrowFlags.Scalar) != 0;
|
||||
bool signedSrc = (flags & SaturatingNarrowFlags.SignedSrc) != 0;
|
||||
bool signedDst = (flags & SaturatingNarrowFlags.SignedDst) != 0;
|
||||
|
||||
|
@ -2034,18 +2034,30 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.SignExtend8 (OperandType.I64, res); break;
|
||||
case 1: res = context.SignExtend16(OperandType.I64, res); break;
|
||||
case 2: res = context.SignExtend32(OperandType.I64, res); break;
|
||||
case 0:
|
||||
res = context.SignExtend8(OperandType.I64, res);
|
||||
break;
|
||||
case 1:
|
||||
res = context.SignExtend16(OperandType.I64, res);
|
||||
break;
|
||||
case 2:
|
||||
res = context.SignExtend32(OperandType.I64, res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.ZeroExtend8 (OperandType.I64, res); break;
|
||||
case 1: res = context.ZeroExtend16(OperandType.I64, res); break;
|
||||
case 2: res = context.ZeroExtend32(OperandType.I64, res); break;
|
||||
case 0:
|
||||
res = context.ZeroExtend8(OperandType.I64, res);
|
||||
break;
|
||||
case 1:
|
||||
res = context.ZeroExtend16(OperandType.I64, res);
|
||||
break;
|
||||
case 2:
|
||||
res = context.ZeroExtend32(OperandType.I64, res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2063,10 +2075,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: vector = context.VectorInsert8 (vector, value, index); break;
|
||||
case 1: vector = context.VectorInsert16(vector, value, index); break;
|
||||
case 2: vector = context.VectorInsert (vector, value, index); break;
|
||||
case 3: vector = context.VectorInsert (vector, value, index); break;
|
||||
case 0:
|
||||
vector = context.VectorInsert8(vector, value, index);
|
||||
break;
|
||||
case 1:
|
||||
vector = context.VectorInsert16(vector, value, index);
|
||||
break;
|
||||
case 2:
|
||||
vector = context.VectorInsert(vector, value, index);
|
||||
break;
|
||||
case 3:
|
||||
vector = context.VectorInsert(vector, value, index);
|
||||
break;
|
||||
}
|
||||
|
||||
return vector;
|
||||
|
|
|
@ -4,7 +4,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -19,18 +18,13 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
public static (int, int) GetQuadwordAndSubindex(int index, RegisterSize size)
|
||||
{
|
||||
switch (size)
|
||||
return size switch
|
||||
{
|
||||
case RegisterSize.Simd128:
|
||||
return (index >> 1, 0);
|
||||
case RegisterSize.Simd64:
|
||||
case RegisterSize.Int64:
|
||||
return (index >> 1, index & 1);
|
||||
case RegisterSize.Int32:
|
||||
return (index >> 2, index & 3);
|
||||
}
|
||||
|
||||
throw new ArgumentException("Unrecognized Vector Register Size.");
|
||||
RegisterSize.Simd128 => (index >> 1, 0),
|
||||
RegisterSize.Simd64 or RegisterSize.Int64 => (index >> 1, index & 1),
|
||||
RegisterSize.Int32 => (index >> 2, index & 3),
|
||||
_ => throw new ArgumentException("Unrecognized Vector Register Size."),
|
||||
};
|
||||
}
|
||||
|
||||
public static Operand ExtractScalar(ArmEmitterContext context, OperandType type, int reg)
|
||||
|
@ -327,7 +321,7 @@ namespace ARMeilleure.Instructions
|
|||
for (int index = 0; index < elems; index++)
|
||||
{
|
||||
Operand ne = EmitVectorExtract32(context, op.Qn, op.In + index, op.Size + 1, signed);
|
||||
Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, signed);
|
||||
Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, signed);
|
||||
|
||||
if (op.Size == 2)
|
||||
{
|
||||
|
@ -380,8 +374,8 @@ namespace ARMeilleure.Instructions
|
|||
for (int index = 0; index < elems; index++)
|
||||
{
|
||||
Operand de = EmitVectorExtract32(context, op.Qd, op.Id + index, op.Size + 1, signed);
|
||||
Operand ne = EmitVectorExtract32(context, op.Qn, op.In + index, op.Size, signed);
|
||||
Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, signed);
|
||||
Operand ne = EmitVectorExtract32(context, op.Qn, op.In + index, op.Size, signed);
|
||||
Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, signed);
|
||||
|
||||
if (op.Size == 2)
|
||||
{
|
||||
|
@ -778,7 +772,10 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
// Index into 0, 0 into index. This swap happens at the start of an A32 scalar op if required.
|
||||
int index = reg & (doubleWidth ? 1 : 3);
|
||||
if (index == 0) return target;
|
||||
if (index == 0)
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
if (doubleWidth)
|
||||
{
|
||||
|
@ -974,7 +971,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Intrinsic inst = (op.Size & 1) != 0 ? inst64 : inst32;
|
||||
|
||||
EmitScalarBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(inst, n, m));
|
||||
EmitScalarBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(inst, n, m));
|
||||
}
|
||||
|
||||
public static void EmitScalarTernaryOpSimd32(ArmEmitterContext context, Func3I scalarFunc)
|
||||
|
@ -1195,7 +1192,7 @@ namespace ARMeilleure.Instructions
|
|||
: typeof(SoftFloat64).GetMethod(name);
|
||||
|
||||
Array.Resize(ref callArgs, callArgs.Length + 1);
|
||||
callArgs[callArgs.Length - 1] = Const(1);
|
||||
callArgs[^1] = Const(1);
|
||||
|
||||
context.ExitArmFpMode();
|
||||
context.StoreToContext();
|
||||
|
@ -1245,16 +1242,24 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.SignExtend8(OperandType.I32, res); break;
|
||||
case 1: res = context.SignExtend16(OperandType.I32, res); break;
|
||||
case 0:
|
||||
res = context.SignExtend8(OperandType.I32, res);
|
||||
break;
|
||||
case 1:
|
||||
res = context.SignExtend16(OperandType.I32, res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.ZeroExtend8(OperandType.I32, res); break;
|
||||
case 1: res = context.ZeroExtend16(OperandType.I32, res); break;
|
||||
case 0:
|
||||
res = context.ZeroExtend8(OperandType.I32, res);
|
||||
break;
|
||||
case 1:
|
||||
res = context.ZeroExtend16(OperandType.I32, res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
|
||||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -74,7 +72,10 @@ namespace ARMeilleure.Instructions
|
|||
public static Operand EmitExtractScalar(ArmEmitterContext context, Operand target, int reg, bool doubleWidth)
|
||||
{
|
||||
int index = reg & (doubleWidth ? 1 : 3);
|
||||
if (index == 0) return target; // Element is already at index 0, so just return the vector directly.
|
||||
if (index == 0)
|
||||
{
|
||||
return target; // Element is already at index 0, so just return the vector directly.
|
||||
}
|
||||
|
||||
if (doubleWidth)
|
||||
{
|
||||
|
@ -249,7 +250,7 @@ namespace ARMeilleure.Instructions
|
|||
OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;
|
||||
|
||||
inst |= ((op.Size & 1) != 0 ? Intrinsic.Arm64VDouble : Intrinsic.Arm64VFloat) | Intrinsic.Arm64V128;
|
||||
EmitScalarBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(inst, n, m));
|
||||
EmitScalarBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(inst, n, m));
|
||||
}
|
||||
|
||||
public static void EmitScalarTernaryOpSimd32(ArmEmitterContext context, Func3I scalarFunc)
|
||||
|
@ -336,16 +337,17 @@ namespace ARMeilleure.Instructions
|
|||
CmpCondition.GreaterThanOrEqual => Intrinsic.Arm64FcmgeVz,
|
||||
CmpCondition.LessThan => Intrinsic.Arm64FcmltVz,
|
||||
CmpCondition.LessThanOrEqual => Intrinsic.Arm64FcmleVz,
|
||||
_ => throw new InvalidOperationException()
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
inst = cond switch
|
||||
{
|
||||
CmpCondition.Equal => Intrinsic.Arm64FcmeqV,
|
||||
CmpCondition.GreaterThan => Intrinsic.Arm64FcmgtV,
|
||||
CmpCondition.GreaterThanOrEqual => Intrinsic.Arm64FcmgeV,
|
||||
_ => throw new InvalidOperationException()
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -367,4 +369,4 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
SetIntOrZR(context, op.Rd, op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (inst, n)
|
||||
? context.AddIntrinsicInt(inst, n)
|
||||
: context.AddIntrinsicLong(inst, n));
|
||||
}
|
||||
|
||||
|
@ -288,7 +288,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
SetIntOrZR(context, op.Rd, op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (inst, n, Const(fBits))
|
||||
? context.AddIntrinsicInt(inst, n, Const(fBits))
|
||||
: context.AddIntrinsicLong(inst, n, Const(fBits)));
|
||||
}
|
||||
|
||||
|
@ -695,7 +695,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
bool cmpWithZero = !(op is OpCodeSimdFcond) ? op.Bit3 : false;
|
||||
bool cmpWithZero = op is not OpCodeSimdFcond && op.Bit3;
|
||||
|
||||
Intrinsic inst = signalNaNs ? Intrinsic.Arm64FcmpeS : Intrinsic.Arm64FcmpS;
|
||||
|
||||
|
@ -717,4 +717,4 @@ namespace ARMeilleure.Instructions
|
|||
SetFlag(context, PState.NFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const(31)), one));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -80,10 +79,11 @@ namespace ARMeilleure.Instructions
|
|||
int eSize = 8 << op.Size;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand imm = eSize switch {
|
||||
Operand imm = eSize switch
|
||||
{
|
||||
16 => X86GetAllElements(context, (short)~op.Immediate),
|
||||
32 => X86GetAllElements(context, (int)~op.Immediate),
|
||||
_ => throw new InvalidOperationException($"Invalid element size {eSize}.")
|
||||
_ => throw new InvalidOperationException($"Invalid element size {eSize}."),
|
||||
};
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Pand, d, imm);
|
||||
|
@ -380,10 +380,11 @@ namespace ARMeilleure.Instructions
|
|||
int eSize = 8 << op.Size;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand imm = eSize switch {
|
||||
Operand imm = eSize switch
|
||||
{
|
||||
16 => X86GetAllElements(context, (short)op.Immediate),
|
||||
32 => X86GetAllElements(context, (int)op.Immediate),
|
||||
_ => throw new InvalidOperationException($"Invalid element size {eSize}.")
|
||||
_ => throw new InvalidOperationException($"Invalid element size {eSize}."),
|
||||
};
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Por, d, imm);
|
||||
|
@ -414,8 +415,8 @@ namespace ARMeilleure.Instructions
|
|||
(0b00010000L << 32) |
|
||||
(0b00001000L << 24) |
|
||||
(0b00000100L << 16) |
|
||||
(0b00000010L << 8) |
|
||||
(0b00000001L << 0);
|
||||
(0b00000010L << 8) |
|
||||
(0b00000001L << 0);
|
||||
|
||||
Operand vBitMatrix = X86GetAllElements(context, bitMatrix);
|
||||
|
||||
|
@ -451,13 +452,13 @@ namespace ARMeilleure.Instructions
|
|||
Debug.Assert(op.Type == OperandType.I64);
|
||||
|
||||
Operand val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xaaul)), Const(1)),
|
||||
context.ShiftLeft (context.BitwiseAnd(op, Const(0x55ul)), Const(1)));
|
||||
context.ShiftLeft(context.BitwiseAnd(op, Const(0x55ul)), Const(1)));
|
||||
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xccul)), Const(2)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x33ul)), Const(2)));
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x33ul)), Const(2)));
|
||||
|
||||
return context.BitwiseOr(context.ShiftRightUI(val, Const(4)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x0ful)), Const(4)));
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x0ful)), Const(4)));
|
||||
}
|
||||
|
||||
public static void Rev16_V(ArmEmitterContext context)
|
||||
|
|
|
@ -52,9 +52,15 @@ namespace ARMeilleure.Instructions
|
|||
// Replicate fields to fill the 64-bits, if size is < 64-bits.
|
||||
switch (op.Size)
|
||||
{
|
||||
case 0: immediate *= 0x0101010101010101L; break;
|
||||
case 1: immediate *= 0x0001000100010001L; break;
|
||||
case 2: immediate *= 0x0000000100000001L; break;
|
||||
case 0:
|
||||
immediate *= 0x0101010101010101L;
|
||||
break;
|
||||
case 1:
|
||||
immediate *= 0x0001000100010001L;
|
||||
break;
|
||||
case 2:
|
||||
immediate *= 0x0000000100000001L;
|
||||
break;
|
||||
}
|
||||
|
||||
Operand imm = Const(immediate);
|
||||
|
@ -199,9 +205,15 @@ namespace ARMeilleure.Instructions
|
|||
// Replicate fields to fill the 64-bits, if size is < 64-bits.
|
||||
switch (op.Size)
|
||||
{
|
||||
case 0: immediate *= 0x0101010101010101L; break;
|
||||
case 1: immediate *= 0x0001000100010001L; break;
|
||||
case 2: immediate *= 0x0000000100000001L; break;
|
||||
case 0:
|
||||
immediate *= 0x0101010101010101L;
|
||||
break;
|
||||
case 1:
|
||||
immediate *= 0x0001000100010001L;
|
||||
break;
|
||||
case 2:
|
||||
immediate *= 0x0000000100000001L;
|
||||
break;
|
||||
}
|
||||
|
||||
Operand imm = Const(immediate);
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
long offset = 0;
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
for (int rep = 0; rep < op.Reps; rep++)
|
||||
for (int elem = 0; elem < op.Elems; elem++)
|
||||
for (int sElem = 0; sElem < op.SElems; sElem++)
|
||||
|
@ -66,6 +67,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
offset += 1 << op.Size;
|
||||
}
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
if (op.WBack)
|
||||
{
|
||||
|
@ -157,4 +159,4 @@ namespace ARMeilleure.Instructions
|
|||
context.Copy(n, context.Add(n, m));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.Translation;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -12,19 +11,19 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
static partial class InstEmit
|
||||
{
|
||||
#region "Masks"
|
||||
#region "Masks"
|
||||
private static readonly long[] _masksE0_Uzp = new long[]
|
||||
{
|
||||
13L << 56 | 09L << 48 | 05L << 40 | 01L << 32 | 12L << 24 | 08L << 16 | 04L << 8 | 00L << 0,
|
||||
11L << 56 | 10L << 48 | 03L << 40 | 02L << 32 | 09L << 24 | 08L << 16 | 01L << 8 | 00L << 0
|
||||
11L << 56 | 10L << 48 | 03L << 40 | 02L << 32 | 09L << 24 | 08L << 16 | 01L << 8 | 00L << 0,
|
||||
};
|
||||
|
||||
private static readonly long[] _masksE1_Uzp = new long[]
|
||||
{
|
||||
15L << 56 | 11L << 48 | 07L << 40 | 03L << 32 | 14L << 24 | 10L << 16 | 06L << 8 | 02L << 0,
|
||||
15L << 56 | 14L << 48 | 07L << 40 | 06L << 32 | 13L << 24 | 12L << 16 | 05L << 8 | 04L << 0
|
||||
15L << 56 | 14L << 48 | 07L << 40 | 06L << 32 | 13L << 24 | 12L << 16 | 05L << 8 | 04L << 0,
|
||||
};
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
public static void Dup_Gp(ArmEmitterContext context)
|
||||
{
|
||||
|
@ -36,9 +35,17 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (op.Size)
|
||||
{
|
||||
case 0: n = context.ZeroExtend8 (n.Type, n); n = context.Multiply(n, Const(n.Type, 0x01010101)); break;
|
||||
case 1: n = context.ZeroExtend16(n.Type, n); n = context.Multiply(n, Const(n.Type, 0x00010001)); break;
|
||||
case 2: n = context.ZeroExtend32(n.Type, n); break;
|
||||
case 0:
|
||||
n = context.ZeroExtend8(n.Type, n);
|
||||
n = context.Multiply(n, Const(n.Type, 0x01010101));
|
||||
break;
|
||||
case 1:
|
||||
n = context.ZeroExtend16(n.Type, n);
|
||||
n = context.Multiply(n, Const(n.Type, 0x00010001));
|
||||
break;
|
||||
case 2:
|
||||
n = context.ZeroExtend32(n.Type, n);
|
||||
break;
|
||||
}
|
||||
|
||||
Operand res = context.VectorInsert(context.VectorZero(), n, 0);
|
||||
|
@ -209,7 +216,7 @@ namespace ARMeilleure.Instructions
|
|||
OpCodeSimdFcond op = (OpCodeSimdFcond)context.CurrOp;
|
||||
|
||||
Operand lblTrue = Label();
|
||||
Operand lblEnd = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
||||
Operand isTrue = InstEmitFlowHelper.GetCondTrue(context, op.Cond);
|
||||
|
||||
|
@ -353,7 +360,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, op.SrcIndex, op.Size);
|
||||
|
||||
context.Copy(d, EmitVectorInsert(context, d, ne, op.DstIndex, op.Size));
|
||||
|
@ -497,8 +504,12 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.Size)
|
||||
{
|
||||
case 0: imm *= 0x01010101; break;
|
||||
case 1: imm *= 0x00010001; break;
|
||||
case 0:
|
||||
imm *= 0x01010101;
|
||||
break;
|
||||
case 1:
|
||||
imm *= 0x00010001;
|
||||
break;
|
||||
}
|
||||
|
||||
if (not)
|
||||
|
@ -543,7 +554,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Operand mMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, m, mask);
|
||||
mMask = context.AddIntrinsic(Intrinsic.X86Por, mMask, m);
|
||||
mMask = context.AddIntrinsic(Intrinsic.X86Por, mMask, m);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mMask);
|
||||
}
|
||||
|
@ -557,7 +568,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand mSubMask = context.AddIntrinsic(Intrinsic.X86Psubb, m, idxMask);
|
||||
|
||||
Operand mMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, mSubMask, mask);
|
||||
mMask = context.AddIntrinsic(Intrinsic.X86Por, mMask, mSubMask);
|
||||
mMask = context.AddIntrinsic(Intrinsic.X86Por, mMask, mSubMask);
|
||||
|
||||
Operand res2 = context.AddIntrinsic(Intrinsic.X86Pshufb, ni, mMask);
|
||||
|
||||
|
@ -566,7 +577,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!isTbl)
|
||||
{
|
||||
Operand idxMask = X86GetAllElements(context, (0x1010101010101010L * op.Size) - 0x0101010101010101L);
|
||||
Operand idxMask = X86GetAllElements(context, (0x1010101010101010L * op.Size) - 0x0101010101010101L);
|
||||
Operand zeroMask = context.VectorZero();
|
||||
|
||||
Operand mPosMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, m, idxMask);
|
||||
|
@ -590,7 +601,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand d = GetVec(op.Rd);
|
||||
|
||||
List<Operand> args = new List<Operand>();
|
||||
List<Operand> args = new();
|
||||
|
||||
if (!isTbl)
|
||||
{
|
||||
|
@ -612,20 +623,36 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (op.Size)
|
||||
{
|
||||
case 1: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)); break;
|
||||
case 2: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)); break;
|
||||
case 3: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3)); break;
|
||||
case 4: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl4)); break;
|
||||
case 1:
|
||||
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3));
|
||||
break;
|
||||
case 4:
|
||||
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl4));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (op.Size)
|
||||
{
|
||||
case 1: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx1)); break;
|
||||
case 2: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)); break;
|
||||
case 3: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)); break;
|
||||
case 4: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)); break;
|
||||
case 1:
|
||||
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx1));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3));
|
||||
break;
|
||||
case 4:
|
||||
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -644,7 +671,7 @@ namespace ARMeilleure.Instructions
|
|||
if (op.Size < 3)
|
||||
{
|
||||
long maskE0 = EvenMasks[op.Size];
|
||||
long maskE1 = OddMasks [op.Size];
|
||||
long maskE1 = OddMasks[op.Size];
|
||||
|
||||
mask = X86GetScalar(context, maskE0);
|
||||
|
||||
|
@ -691,7 +718,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand ne = EmitVectorExtractZx(context, op.Rn, pairIndex + part, op.Size);
|
||||
Operand me = EmitVectorExtractZx(context, op.Rm, pairIndex + part, op.Size);
|
||||
|
||||
res = EmitVectorInsert(context, res, ne, pairIndex, op.Size);
|
||||
res = EmitVectorInsert(context, res, ne, pairIndex, op.Size);
|
||||
res = EmitVectorInsert(context, res, me, pairIndex + 1, op.Size);
|
||||
}
|
||||
|
||||
|
@ -712,7 +739,7 @@ namespace ARMeilleure.Instructions
|
|||
if (op.Size < 3)
|
||||
{
|
||||
long maskE0 = EvenMasks[op.Size];
|
||||
long maskE1 = OddMasks [op.Size];
|
||||
long maskE1 = OddMasks[op.Size];
|
||||
|
||||
mask = X86GetScalar(context, maskE0);
|
||||
|
||||
|
@ -784,7 +811,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand ne = EmitVectorExtractZx(context, op.Rn, idx + part, op.Size);
|
||||
Operand me = EmitVectorExtractZx(context, op.Rm, idx + part, op.Size);
|
||||
|
||||
res = EmitVectorInsert(context, res, ne, index, op.Size);
|
||||
res = EmitVectorInsert(context, res, ne, index, op.Size);
|
||||
res = EmitVectorInsert(context, res, me, pairs + index, op.Size);
|
||||
}
|
||||
|
||||
|
@ -839,7 +866,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand ne = EmitVectorExtractZx(context, op.Rn, baseIndex + index, op.Size);
|
||||
Operand me = EmitVectorExtractZx(context, op.Rm, baseIndex + index, op.Size);
|
||||
|
||||
res = EmitVectorInsert(context, res, ne, pairIndex, op.Size);
|
||||
res = EmitVectorInsert(context, res, ne, pairIndex, op.Size);
|
||||
res = EmitVectorInsert(context, res, me, pairIndex + 1, op.Size);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
|
||||
|
@ -17,13 +16,13 @@ namespace ARMeilleure.Instructions
|
|||
private static readonly long[] _masksE0_Uzp = new long[]
|
||||
{
|
||||
13L << 56 | 09L << 48 | 05L << 40 | 01L << 32 | 12L << 24 | 08L << 16 | 04L << 8 | 00L << 0,
|
||||
11L << 56 | 10L << 48 | 03L << 40 | 02L << 32 | 09L << 24 | 08L << 16 | 01L << 8 | 00L << 0
|
||||
11L << 56 | 10L << 48 | 03L << 40 | 02L << 32 | 09L << 24 | 08L << 16 | 01L << 8 | 00L << 0,
|
||||
};
|
||||
|
||||
private static readonly long[] _masksE1_Uzp = new long[]
|
||||
{
|
||||
15L << 56 | 11L << 48 | 07L << 40 | 03L << 32 | 14L << 24 | 10L << 16 | 06L << 8 | 02L << 0,
|
||||
15L << 56 | 14L << 48 | 07L << 40 | 06L << 32 | 13L << 24 | 12L << 16 | 05L << 8 | 04L << 0
|
||||
15L << 56 | 14L << 48 | 07L << 40 | 06L << 32 | 13L << 24 | 12L << 16 | 05L << 8 | 04L << 0,
|
||||
};
|
||||
#endregion
|
||||
|
||||
|
@ -220,7 +219,7 @@ namespace ARMeilleure.Instructions
|
|||
for (int index = 1; index < length; index++)
|
||||
{
|
||||
int newVn = (op.Vn + index) & 0x1F;
|
||||
(int qn, int ind) = GetQuadwordAndSubindex(newVn, op.RegisterSize);
|
||||
(int qn, _) = GetQuadwordAndSubindex(newVn, op.RegisterSize);
|
||||
Operand ni = EmitMoveDoubleWordToSide(context, GetVecA32(qn), newVn, 0);
|
||||
|
||||
Operand idxMask = X86GetAllElements(context, 0x0808080808080808L * index);
|
||||
|
|
|
@ -6,7 +6,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -17,12 +16,12 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
static partial class InstEmit
|
||||
{
|
||||
#region "Masks"
|
||||
#region "Masks"
|
||||
private static readonly long[] _masks_SliSri = new long[] // Replication masks.
|
||||
{
|
||||
0x0101010101010101L, 0x0001000100010001L, 0x0000000100000001L, 0x0000000000000001L
|
||||
0x0101010101010101L, 0x0001000100010001L, 0x0000000100000001L, 0x0000000000000001L,
|
||||
};
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
public static void Rshrn_V(ArmEmitterContext context)
|
||||
{
|
||||
|
@ -51,9 +50,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.Size + 1)
|
||||
{
|
||||
case 1: mask = X86GetAllElements(context, (int)roundConst * 0x00010001); break;
|
||||
case 2: mask = X86GetAllElements(context, (int)roundConst); break;
|
||||
case 3: mask = X86GetAllElements(context, roundConst); break;
|
||||
case 1:
|
||||
mask = X86GetAllElements(context, (int)roundConst * 0x00010001);
|
||||
break;
|
||||
case 2:
|
||||
mask = X86GetAllElements(context, (int)roundConst);
|
||||
break;
|
||||
case 3:
|
||||
mask = X86GetAllElements(context, roundConst);
|
||||
break;
|
||||
}
|
||||
|
||||
Intrinsic addInst = X86PaddInstruction[op.Size + 1];
|
||||
|
@ -1174,14 +1179,14 @@ namespace ARMeilleure.Instructions
|
|||
Scalar = 1 << 0,
|
||||
Signed = 1 << 1,
|
||||
|
||||
Round = 1 << 2,
|
||||
Round = 1 << 2,
|
||||
Accumulate = 1 << 3,
|
||||
|
||||
ScalarSx = Scalar | Signed,
|
||||
ScalarZx = Scalar,
|
||||
|
||||
VectorSx = Signed,
|
||||
VectorZx = 0
|
||||
VectorZx = 0,
|
||||
}
|
||||
|
||||
private static void EmitScalarShrImmOpSx(ArmEmitterContext context, ShrImmFlags flags)
|
||||
|
@ -1210,9 +1215,9 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand res = context.VectorZero();
|
||||
|
||||
bool scalar = (flags & ShrImmFlags.Scalar) != 0;
|
||||
bool signed = (flags & ShrImmFlags.Signed) != 0;
|
||||
bool round = (flags & ShrImmFlags.Round) != 0;
|
||||
bool scalar = (flags & ShrImmFlags.Scalar) != 0;
|
||||
bool signed = (flags & ShrImmFlags.Signed) != 0;
|
||||
bool round = (flags & ShrImmFlags.Round) != 0;
|
||||
bool accumulate = (flags & ShrImmFlags.Accumulate) != 0;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
@ -1288,7 +1293,7 @@ namespace ARMeilleure.Instructions
|
|||
[Flags]
|
||||
private enum ShrImmSaturatingNarrowFlags
|
||||
{
|
||||
Scalar = 1 << 0,
|
||||
Scalar = 1 << 0,
|
||||
SignedSrc = 1 << 1,
|
||||
SignedDst = 1 << 2,
|
||||
|
||||
|
@ -1300,7 +1305,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
VectorSxSx = SignedSrc | SignedDst,
|
||||
VectorSxZx = SignedSrc,
|
||||
VectorZxZx = 0
|
||||
VectorZxZx = 0,
|
||||
}
|
||||
|
||||
private static void EmitRoundShrImmSaturatingNarrowOp(ArmEmitterContext context, ShrImmSaturatingNarrowFlags flags)
|
||||
|
@ -1312,10 +1317,10 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||
|
||||
bool scalar = (flags & ShrImmSaturatingNarrowFlags.Scalar) != 0;
|
||||
bool scalar = (flags & ShrImmSaturatingNarrowFlags.Scalar) != 0;
|
||||
bool signedSrc = (flags & ShrImmSaturatingNarrowFlags.SignedSrc) != 0;
|
||||
bool signedDst = (flags & ShrImmSaturatingNarrowFlags.SignedDst) != 0;
|
||||
bool round = (flags & ShrImmSaturatingNarrowFlags.Round) != 0;
|
||||
bool round = (flags & ShrImmSaturatingNarrowFlags.Round) != 0;
|
||||
|
||||
int shift = GetImmShr(op);
|
||||
|
||||
|
@ -1585,7 +1590,7 @@ namespace ARMeilleure.Instructions
|
|||
Scalar = 1 << 0,
|
||||
Signed = 1 << 1,
|
||||
Round = 1 << 2,
|
||||
Saturating = 1 << 3
|
||||
Saturating = 1 << 3,
|
||||
}
|
||||
|
||||
private static void EmitShlRegOp(ArmEmitterContext context, ShlRegFlags flags = ShlRegFlags.None)
|
||||
|
|
|
@ -5,7 +5,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
|
||||
|
@ -291,7 +290,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
VectorSxSx = SignedSrc | SignedDst,
|
||||
VectorSxZx = SignedSrc,
|
||||
VectorZxZx = 0
|
||||
VectorZxZx = 0,
|
||||
}
|
||||
|
||||
private static void EmitRoundShrImmSaturatingNarrowOp(ArmEmitterContext context, ShrImmSaturatingNarrowFlags flags)
|
||||
|
@ -303,10 +302,10 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
|
||||
|
||||
bool scalar = (flags & ShrImmSaturatingNarrowFlags.Scalar) != 0;
|
||||
bool scalar = (flags & ShrImmSaturatingNarrowFlags.Scalar) != 0;
|
||||
bool signedSrc = (flags & ShrImmSaturatingNarrowFlags.SignedSrc) != 0;
|
||||
bool signedDst = (flags & ShrImmSaturatingNarrowFlags.SignedDst) != 0;
|
||||
bool round = (flags & ShrImmSaturatingNarrowFlags.Round) != 0;
|
||||
bool round = (flags & ShrImmSaturatingNarrowFlags.Round) != 0;
|
||||
|
||||
if (scalar)
|
||||
{
|
||||
|
|
|
@ -28,18 +28,39 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (GetPackedId(op))
|
||||
{
|
||||
case 0b11_011_0000_0000_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)); break;
|
||||
case 0b11_011_0000_0000_111: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)); break;
|
||||
case 0b11_011_0100_0010_000: EmitGetNzcv(context); return;
|
||||
case 0b11_011_0100_0100_000: EmitGetFpcr(context); return;
|
||||
case 0b11_011_0100_0100_001: EmitGetFpsr(context); return;
|
||||
case 0b11_011_1101_0000_010: EmitGetTpidrEl0(context); return;
|
||||
case 0b11_011_1101_0000_011: EmitGetTpidrroEl0(context); return;
|
||||
case 0b11_011_1110_0000_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)); break;
|
||||
case 0b11_011_1110_0000_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)); break;
|
||||
case 0b11_011_1110_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)); break;
|
||||
case 0b11_011_0000_0000_001:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0));
|
||||
break;
|
||||
case 0b11_011_0000_0000_111:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0));
|
||||
break;
|
||||
case 0b11_011_0100_0010_000:
|
||||
EmitGetNzcv(context);
|
||||
return;
|
||||
case 0b11_011_0100_0100_000:
|
||||
EmitGetFpcr(context);
|
||||
return;
|
||||
case 0b11_011_0100_0100_001:
|
||||
EmitGetFpsr(context);
|
||||
return;
|
||||
case 0b11_011_1101_0000_010:
|
||||
EmitGetTpidrEl0(context);
|
||||
return;
|
||||
case 0b11_011_1101_0000_011:
|
||||
EmitGetTpidrroEl0(context);
|
||||
return;
|
||||
case 0b11_011_1110_0000_000:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0));
|
||||
break;
|
||||
case 0b11_011_1110_0000_001:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0));
|
||||
break;
|
||||
case 0b11_011_1110_0000_010:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0));
|
||||
break;
|
||||
|
||||
default: throw new NotImplementedException($"Unknown MRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
SetIntOrZR(context, op.Rt, context.Call(info));
|
||||
|
@ -51,12 +72,21 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (GetPackedId(op))
|
||||
{
|
||||
case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
|
||||
case 0b11_011_0100_0100_000: EmitSetFpcr(context); return;
|
||||
case 0b11_011_0100_0100_001: EmitSetFpsr(context); return;
|
||||
case 0b11_011_1101_0000_010: EmitSetTpidrEl0(context); return;
|
||||
case 0b11_011_0100_0010_000:
|
||||
EmitSetNzcv(context);
|
||||
return;
|
||||
case 0b11_011_0100_0100_000:
|
||||
EmitSetFpcr(context);
|
||||
return;
|
||||
case 0b11_011_0100_0100_001:
|
||||
EmitSetFpsr(context);
|
||||
return;
|
||||
case 0b11_011_1101_0000_010:
|
||||
EmitSetTpidrEl0(context);
|
||||
return;
|
||||
|
||||
default: throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,20 +105,20 @@ namespace ARMeilleure.Instructions
|
|||
switch (GetPackedId(op))
|
||||
{
|
||||
case 0b11_011_0111_0100_001:
|
||||
{
|
||||
// DC ZVA
|
||||
Operand t = GetIntOrZR(context, op.Rt);
|
||||
|
||||
for (long offset = 0; offset < DczSizeInBytes; offset += 8)
|
||||
{
|
||||
Operand address = context.Add(t, Const(offset));
|
||||
// DC ZVA
|
||||
Operand t = GetIntOrZR(context, op.Rt);
|
||||
|
||||
InstEmitMemoryHelper.EmitStore(context, address, RegisterConsts.ZeroIndex, 3);
|
||||
for (long offset = 0; offset < DczSizeInBytes; offset += 8)
|
||||
{
|
||||
Operand address = context.Add(t, Const(offset));
|
||||
|
||||
InstEmitMemoryHelper.EmitStore(context, address, RegisterConsts.ZeroIndex, 3);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// No-op
|
||||
case 0b11_011_0111_1110_001: // DC CIVAC
|
||||
break;
|
||||
|
@ -104,7 +134,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
int id;
|
||||
|
||||
id = op.Op2 << 0;
|
||||
id = op.Op2 << 0;
|
||||
id |= op.CRm << 3;
|
||||
id |= op.CRn << 7;
|
||||
id |= op.Op1 << 11;
|
||||
|
@ -188,7 +218,7 @@ namespace ARMeilleure.Instructions
|
|||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Operand nzcv = GetIntOrZR(context, op.Rt);
|
||||
nzcv = context.ConvertI64ToI32(nzcv);
|
||||
nzcv = context.ConvertI64ToI32(nzcv);
|
||||
|
||||
SetFlag(context, PState.VFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.VFlag)), Const(1)));
|
||||
SetFlag(context, PState.CFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.CFlag)), Const(1)));
|
||||
|
@ -201,7 +231,7 @@ namespace ARMeilleure.Instructions
|
|||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Operand fpcr = GetIntOrZR(context, op.Rt);
|
||||
fpcr = context.ConvertI64ToI32(fpcr);
|
||||
fpcr = context.ConvertI64ToI32(fpcr);
|
||||
|
||||
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||
{
|
||||
|
@ -221,7 +251,7 @@ namespace ARMeilleure.Instructions
|
|||
context.ClearQcFlagIfModified();
|
||||
|
||||
Operand fpsr = GetIntOrZR(context, op.Rt);
|
||||
fpsr = context.ConvertI64ToI32(fpsr);
|
||||
fpsr = context.ConvertI64ToI32(fpsr);
|
||||
|
||||
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||
{
|
||||
|
|
|
@ -4,7 +4,6 @@ using ARMeilleure.State;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -34,7 +33,8 @@ namespace ARMeilleure.Instructions
|
|||
switch (op.Opc2)
|
||||
{
|
||||
case 2:
|
||||
EmitSetTpidrEl0(context); return;
|
||||
EmitSetTpidrEl0(context);
|
||||
return;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
|
||||
|
@ -83,17 +83,13 @@ namespace ARMeilleure.Instructions
|
|||
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
|
||||
}
|
||||
|
||||
switch (op.Opc2)
|
||||
result = op.Opc2 switch
|
||||
{
|
||||
case 2:
|
||||
result = EmitGetTpidrEl0(context); break;
|
||||
|
||||
case 3:
|
||||
result = EmitGetTpidrroEl0(context); break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
|
||||
}
|
||||
2 => EmitGetTpidrEl0(context),
|
||||
3 => EmitGetTpidrroEl0(context),
|
||||
_ => throw new NotImplementedException(
|
||||
$"Unknown MRC Opc2 0x{op.Opc2:X} at 0x{op.Address:X} (0x{op.RawOpCode:X})."),
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
|
@ -126,27 +122,16 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
int opc = op.MrrcOp;
|
||||
|
||||
MethodInfo info;
|
||||
|
||||
switch (op.CRm)
|
||||
MethodInfo info = op.CRm switch
|
||||
{
|
||||
case 14: // Timer.
|
||||
switch (opc)
|
||||
{
|
||||
case 0:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)); break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRRC Opc1 0x{opc:X} at 0x{op.Address:X} (0x{op.RawOpCode:X}).");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRRC 0x{op.RawOpCode:X} at 0x{op.Address:X}.");
|
||||
}
|
||||
|
||||
// Timer.
|
||||
14 => opc switch
|
||||
{
|
||||
0 => typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)),
|
||||
_ => throw new NotImplementedException($"Unknown MRRC Opc1 0x{opc:X} at 0x{op.Address:X} (0x{op.RawOpCode:X})."),
|
||||
},
|
||||
_ => throw new NotImplementedException($"Unknown MRRC 0x{op.RawOpCode:X} at 0x{op.Address:X}."),
|
||||
};
|
||||
Operand result = context.Call(info);
|
||||
|
||||
SetIntA32(context, op.Rt, context.ConvertI64ToI32(result));
|
||||
|
@ -235,7 +220,8 @@ namespace ARMeilleure.Instructions
|
|||
case 0b0000: // FPSID
|
||||
throw new NotImplementedException("Supervisor Only");
|
||||
case 0b0001: // FPSCR
|
||||
EmitGetFpscr(context); return;
|
||||
EmitGetFpscr(context);
|
||||
return;
|
||||
case 0b0101: // MVFR2
|
||||
throw new NotImplementedException("MVFR2");
|
||||
case 0b0110: // MVFR1
|
||||
|
@ -258,7 +244,8 @@ namespace ARMeilleure.Instructions
|
|||
case 0b0000: // FPSID
|
||||
throw new NotImplementedException("Supervisor Only");
|
||||
case 0b0001: // FPSCR
|
||||
EmitSetFpscr(context); return;
|
||||
EmitSetFpscr(context);
|
||||
return;
|
||||
case 0b0101: // MVFR2
|
||||
throw new NotImplementedException("MVFR2");
|
||||
case 0b0110: // MVFR1
|
||||
|
|
|
@ -64,12 +64,12 @@ namespace ARMeilleure.Instructions
|
|||
#region "System registers"
|
||||
public static ulong GetCtrEl0()
|
||||
{
|
||||
return (ulong)GetContext().CtrEl0;
|
||||
return GetContext().CtrEl0;
|
||||
}
|
||||
|
||||
public static ulong GetDczidEl0()
|
||||
{
|
||||
return (ulong)GetContext().DczidEl0;
|
||||
return GetContext().DczidEl0;
|
||||
}
|
||||
|
||||
public static ulong GetCntfrqEl0()
|
||||
|
@ -192,4 +192,4 @@ namespace ARMeilleure.Instructions
|
|||
return Context.Memory;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
static class SoftFallback
|
||||
{
|
||||
#region "ShrImm64"
|
||||
#region "ShrImm64"
|
||||
public static long SignedShrImm64(long value, long roundConst, int shift)
|
||||
{
|
||||
if (roundConst == 0L)
|
||||
|
@ -89,12 +89,15 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "Saturation"
|
||||
#region "Saturation"
|
||||
public static int SatF32ToS32(float value)
|
||||
{
|
||||
if (float.IsNaN(value)) return 0;
|
||||
if (float.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= int.MaxValue ? int.MaxValue :
|
||||
value <= int.MinValue ? int.MinValue : (int)value;
|
||||
|
@ -102,7 +105,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static long SatF32ToS64(float value)
|
||||
{
|
||||
if (float.IsNaN(value)) return 0;
|
||||
if (float.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= long.MaxValue ? long.MaxValue :
|
||||
value <= long.MinValue ? long.MinValue : (long)value;
|
||||
|
@ -110,7 +116,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static uint SatF32ToU32(float value)
|
||||
{
|
||||
if (float.IsNaN(value)) return 0;
|
||||
if (float.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= uint.MaxValue ? uint.MaxValue :
|
||||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||
|
@ -118,7 +127,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static ulong SatF32ToU64(float value)
|
||||
{
|
||||
if (float.IsNaN(value)) return 0;
|
||||
if (float.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= ulong.MaxValue ? ulong.MaxValue :
|
||||
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
|
||||
|
@ -126,7 +138,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static int SatF64ToS32(double value)
|
||||
{
|
||||
if (double.IsNaN(value)) return 0;
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= int.MaxValue ? int.MaxValue :
|
||||
value <= int.MinValue ? int.MinValue : (int)value;
|
||||
|
@ -134,7 +149,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static long SatF64ToS64(double value)
|
||||
{
|
||||
if (double.IsNaN(value)) return 0;
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= long.MaxValue ? long.MaxValue :
|
||||
value <= long.MinValue ? long.MinValue : (long)value;
|
||||
|
@ -142,7 +160,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static uint SatF64ToU32(double value)
|
||||
{
|
||||
if (double.IsNaN(value)) return 0;
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= uint.MaxValue ? uint.MaxValue :
|
||||
value <= uint.MinValue ? uint.MinValue : (uint)value;
|
||||
|
@ -150,14 +171,17 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static ulong SatF64ToU64(double value)
|
||||
{
|
||||
if (double.IsNaN(value)) return 0;
|
||||
if (double.IsNaN(value))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return value >= ulong.MaxValue ? ulong.MaxValue :
|
||||
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "Count"
|
||||
#region "Count"
|
||||
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
||||
{
|
||||
value ^= value >> 1;
|
||||
|
@ -197,9 +221,9 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
return (ulong)count;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "Table"
|
||||
#region "Table"
|
||||
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
|
||||
{
|
||||
return TblOrTbx(default, vector, bytes, tb0);
|
||||
|
@ -270,21 +294,21 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
return new V128(res);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "Crc32"
|
||||
private const uint Crc32RevPoly = 0xedb88320;
|
||||
#region "Crc32"
|
||||
private const uint Crc32RevPoly = 0xedb88320;
|
||||
private const uint Crc32cRevPoly = 0x82f63b78;
|
||||
|
||||
public static uint Crc32b(uint crc, byte value) => Crc32 (crc, Crc32RevPoly, value);
|
||||
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
|
||||
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
|
||||
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
|
||||
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
|
||||
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
|
||||
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
|
||||
|
||||
public static uint Crc32cb(uint crc, byte value) => Crc32 (crc, Crc32cRevPoly, value);
|
||||
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
|
||||
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
|
||||
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
|
||||
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
|
||||
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
|
||||
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
|
||||
|
||||
private static uint Crc32h(uint crc, uint poly, ushort val)
|
||||
{
|
||||
|
@ -331,9 +355,9 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
return crc;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "Aes"
|
||||
#region "Aes"
|
||||
public static V128 Decrypt(V128 value, V128 roundKey)
|
||||
{
|
||||
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
|
||||
|
@ -353,9 +377,9 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
return CryptoHelper.AesMixColumns(value);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "Sha1"
|
||||
#region "Sha1"
|
||||
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
|
||||
{
|
||||
for (int e = 0; e <= 3; e++)
|
||||
|
@ -426,7 +450,7 @@ namespace ARMeilleure.Instructions
|
|||
ulong t2 = w4_7.Extract<ulong>(0);
|
||||
ulong t1 = w0_3.Extract<ulong>(1);
|
||||
|
||||
V128 result = new V128(t1, t2);
|
||||
V128 result = new(t1, t2);
|
||||
|
||||
return result ^ (w0_3 ^ w8_11);
|
||||
}
|
||||
|
@ -472,9 +496,9 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
return (value << count) | (value >> (32 - count));
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "Sha256"
|
||||
#region "Sha256"
|
||||
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
|
||||
{
|
||||
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
|
||||
|
@ -487,7 +511,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
|
||||
{
|
||||
V128 result = new V128();
|
||||
V128 result = new();
|
||||
|
||||
for (int e = 0; e <= 3; e++)
|
||||
{
|
||||
|
@ -505,7 +529,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
|
||||
{
|
||||
V128 result = new V128();
|
||||
V128 result = new();
|
||||
|
||||
ulong t1 = w12_15.Extract<ulong>(1);
|
||||
|
||||
|
@ -602,13 +626,13 @@ namespace ARMeilleure.Instructions
|
|||
? (uint)(value & 0xFFFFFFFFUL)
|
||||
: (uint)(value >> 32);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
|
||||
{
|
||||
V128 result = V128.Zero;
|
||||
|
||||
V128 op2_128 = new V128(op2, 0);
|
||||
V128 op2_128 = new(op2, 0);
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
static SoftFloat()
|
||||
{
|
||||
RecipEstimateTable = BuildRecipEstimateTable();
|
||||
RecipEstimateTable = BuildRecipEstimateTable();
|
||||
RecipSqrtEstimateTable = BuildRecipSqrtEstimateTable();
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
while (src * (aux + 1u) * (aux + 1u) < (1u << 28))
|
||||
{
|
||||
aux = aux + 1u;
|
||||
aux++;
|
||||
}
|
||||
|
||||
uint dst = (aux + 1u) >> 1;
|
||||
|
@ -133,8 +133,8 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
sign = (~(uint)valueBits & 0x8000u) == 0u;
|
||||
|
||||
uint exp16 = ((uint)valueBits & 0x7C00u) >> 10;
|
||||
uint frac16 = (uint)valueBits & 0x03FFu;
|
||||
uint exp16 = ((uint)valueBits & 0x7C00u) >> 10;
|
||||
uint frac16 = (uint)valueBits & 0x03FFu;
|
||||
|
||||
double real;
|
||||
|
||||
|
@ -180,17 +180,17 @@ namespace ARMeilleure.Instructions
|
|||
const int e = 5;
|
||||
const int f = 10;
|
||||
|
||||
bool sign;
|
||||
bool sign;
|
||||
double mantissa;
|
||||
|
||||
if (real < 0d)
|
||||
{
|
||||
sign = true;
|
||||
sign = true;
|
||||
mantissa = -real;
|
||||
}
|
||||
else
|
||||
{
|
||||
sign = false;
|
||||
sign = false;
|
||||
mantissa = real;
|
||||
}
|
||||
|
||||
|
@ -229,22 +229,22 @@ namespace ARMeilleure.Instructions
|
|||
switch (context.Fpcr.GetRoundingMode())
|
||||
{
|
||||
case FPRoundingMode.ToNearest:
|
||||
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
|
||||
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
|
||||
overflowToInf = true;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsPlusInfinity:
|
||||
roundUp = (error != 0d && !sign);
|
||||
roundUp = (error != 0d && !sign);
|
||||
overflowToInf = !sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsMinusInfinity:
|
||||
roundUp = (error != 0d && sign);
|
||||
roundUp = (error != 0d && sign);
|
||||
overflowToInf = sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsZero:
|
||||
roundUp = false;
|
||||
roundUp = false;
|
||||
overflowToInf = false;
|
||||
break;
|
||||
|
||||
|
@ -359,17 +359,17 @@ namespace ARMeilleure.Instructions
|
|||
const int e = 8;
|
||||
const int f = 23;
|
||||
|
||||
bool sign;
|
||||
bool sign;
|
||||
double mantissa;
|
||||
|
||||
if (real < 0d)
|
||||
{
|
||||
sign = true;
|
||||
sign = true;
|
||||
mantissa = -real;
|
||||
}
|
||||
else
|
||||
{
|
||||
sign = false;
|
||||
sign = false;
|
||||
mantissa = real;
|
||||
}
|
||||
|
||||
|
@ -415,22 +415,22 @@ namespace ARMeilleure.Instructions
|
|||
switch (context.Fpcr.GetRoundingMode())
|
||||
{
|
||||
case FPRoundingMode.ToNearest:
|
||||
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
|
||||
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
|
||||
overflowToInf = true;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsPlusInfinity:
|
||||
roundUp = (error != 0d && !sign);
|
||||
roundUp = (error != 0d && !sign);
|
||||
overflowToInf = !sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsMinusInfinity:
|
||||
roundUp = (error != 0d && sign);
|
||||
roundUp = (error != 0d && sign);
|
||||
overflowToInf = sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsZero:
|
||||
roundUp = false;
|
||||
roundUp = false;
|
||||
overflowToInf = false;
|
||||
break;
|
||||
|
||||
|
@ -534,17 +534,17 @@ namespace ARMeilleure.Instructions
|
|||
const int e = 11;
|
||||
const int f = 52;
|
||||
|
||||
bool sign;
|
||||
bool sign;
|
||||
double mantissa;
|
||||
|
||||
if (real < 0d)
|
||||
{
|
||||
sign = true;
|
||||
sign = true;
|
||||
mantissa = -real;
|
||||
}
|
||||
else
|
||||
{
|
||||
sign = false;
|
||||
sign = false;
|
||||
mantissa = real;
|
||||
}
|
||||
|
||||
|
@ -590,22 +590,22 @@ namespace ARMeilleure.Instructions
|
|||
switch (context.Fpcr.GetRoundingMode())
|
||||
{
|
||||
case FPRoundingMode.ToNearest:
|
||||
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
|
||||
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
|
||||
overflowToInf = true;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsPlusInfinity:
|
||||
roundUp = (error != 0d && !sign);
|
||||
roundUp = (error != 0d && !sign);
|
||||
overflowToInf = !sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsMinusInfinity:
|
||||
roundUp = (error != 0d && sign);
|
||||
roundUp = (error != 0d && sign);
|
||||
overflowToInf = sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsZero:
|
||||
roundUp = false;
|
||||
roundUp = false;
|
||||
overflowToInf = false;
|
||||
break;
|
||||
|
||||
|
@ -728,8 +728,8 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
sign = (~valueBits & 0x80000000u) == 0u;
|
||||
|
||||
uint exp32 = (valueBits & 0x7F800000u) >> 23;
|
||||
uint frac32 = valueBits & 0x007FFFFFu;
|
||||
uint exp32 = (valueBits & 0x7F800000u) >> 23;
|
||||
uint frac32 = valueBits & 0x007FFFFFu;
|
||||
|
||||
double real;
|
||||
|
||||
|
@ -798,8 +798,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if (inf1 && inf2 && sign1 == !sign2)
|
||||
{
|
||||
|
@ -840,8 +842,8 @@ namespace ARMeilleure.Instructions
|
|||
ExecutionContext context = NativeInterface.GetContext();
|
||||
FPCR fpcr = context.Fpcr;
|
||||
|
||||
value1 = value1.FPUnpack(out FPType type1, out bool sign1, out _, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out bool sign2, out _, context, fpcr);
|
||||
value1 = value1.FPUnpack(out FPType type1, out _, out _, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out _, out _, context, fpcr);
|
||||
|
||||
int result;
|
||||
|
||||
|
@ -995,8 +997,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if ((inf1 && inf2) || (zero1 && zero2))
|
||||
{
|
||||
|
@ -1232,8 +1236,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if ((inf1 && zero2) || (zero1 && inf2))
|
||||
{
|
||||
|
@ -1276,11 +1282,13 @@ namespace ARMeilleure.Instructions
|
|||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||
|
||||
valueA = valueA.FPUnpack(out FPType typeA, out bool signA, out uint addend, context, fpcr);
|
||||
value1 = value1.FPUnpack(out FPType type1, out bool sign1, out uint op1, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out bool sign2, out uint op2, context, fpcr);
|
||||
value1 = value1.FPUnpack(out FPType type1, out bool sign1, out uint op1, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out bool sign2, out uint op2, context, fpcr);
|
||||
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
float result = FPProcessNaNs3(typeA, type1, type2, addend, op1, op2, out bool done, context, fpcr);
|
||||
|
||||
|
@ -1293,10 +1301,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool infA = typeA == FPType.Infinity; bool zeroA = typeA == FPType.Zero;
|
||||
bool infA = typeA == FPType.Infinity;
|
||||
bool zeroA = typeA == FPType.Zero;
|
||||
|
||||
bool signP = sign1 ^ sign2;
|
||||
bool infP = inf1 || inf2;
|
||||
bool signP = sign1 ^ sign2;
|
||||
bool infP = inf1 || inf2;
|
||||
bool zeroP = zero1 || zero2;
|
||||
|
||||
if ((inf1 && zero2) || (zero1 && inf2) || (infA && infP && signA != signP))
|
||||
|
@ -1359,8 +1368,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if ((inf1 && zero2) || (zero1 && inf2))
|
||||
{
|
||||
|
@ -1435,34 +1446,17 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else if (MathF.Abs(value) < MathF.Pow(2f, -128))
|
||||
{
|
||||
bool overflowToInf;
|
||||
|
||||
switch (fpcr.GetRoundingMode())
|
||||
var overflowToInf = fpcr.GetRoundingMode() switch
|
||||
{
|
||||
case FPRoundingMode.ToNearest:
|
||||
overflowToInf = true;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsPlusInfinity:
|
||||
overflowToInf = !sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsMinusInfinity:
|
||||
overflowToInf = sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsZero:
|
||||
overflowToInf = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Invalid rounding mode \"{fpcr.GetRoundingMode()}\".");
|
||||
}
|
||||
|
||||
FPRoundingMode.TowardsPlusInfinity => !sign,
|
||||
FPRoundingMode.TowardsMinusInfinity => sign,
|
||||
FPRoundingMode.TowardsZero => false,
|
||||
_ => throw new ArgumentException($"Invalid rounding mode \"{fpcr.GetRoundingMode()}\"."),
|
||||
};
|
||||
result = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign);
|
||||
|
||||
SoftFloat.FPProcessException(FPException.Overflow, context, fpcr);
|
||||
SoftFloat.FPProcessException(FPException.Inexact, context, fpcr);
|
||||
SoftFloat.FPProcessException(FPException.Inexact, context, fpcr);
|
||||
}
|
||||
else if ((fpcr & FPCR.Fz) != 0 && (MathF.Abs(value) >= MathF.Pow(2f, 126)))
|
||||
{
|
||||
|
@ -1518,15 +1512,17 @@ namespace ARMeilleure.Instructions
|
|||
ExecutionContext context = NativeInterface.GetContext();
|
||||
FPCR fpcr = context.StandardFpcrValue;
|
||||
|
||||
value1 = value1.FPUnpack(out FPType type1, out bool sign1, out uint op1, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out bool sign2, out uint op2, context, fpcr);
|
||||
value1 = value1.FPUnpack(out FPType type1, out _, out uint op1, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out _, out uint op2, context, fpcr);
|
||||
|
||||
float result = FPProcessNaNs(type1, type2, op1, op2, out bool done, context, fpcr);
|
||||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
float product;
|
||||
|
||||
|
@ -1559,8 +1555,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if ((inf1 && zero2) || (zero1 && inf2))
|
||||
{
|
||||
|
@ -1691,8 +1689,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if (inf1 && inf2 && sign1 == sign2)
|
||||
{
|
||||
|
@ -1733,15 +1733,17 @@ namespace ARMeilleure.Instructions
|
|||
ExecutionContext context = NativeInterface.GetContext();
|
||||
FPCR fpcr = context.StandardFpcrValue;
|
||||
|
||||
value1 = value1.FPUnpack(out FPType type1, out bool sign1, out uint op1, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out bool sign2, out uint op2, context, fpcr);
|
||||
value1 = value1.FPUnpack(out FPType type1, out _, out uint op1, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out _, out uint op2, context, fpcr);
|
||||
|
||||
float result = FPProcessNaNs(type1, type2, op1, op2, out bool done, context, fpcr);
|
||||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
float product;
|
||||
|
||||
|
@ -1774,8 +1776,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if ((inf1 && zero2) || (zero1 && inf2))
|
||||
{
|
||||
|
@ -1860,8 +1864,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if (inf1 && inf2 && sign1 == sign2)
|
||||
{
|
||||
|
@ -1958,7 +1964,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if ((valueBits & 0x007FFFFFu) == 0u || (fpcr & FPCR.Fz) != 0)
|
||||
{
|
||||
type = FPType.Zero;
|
||||
type = FPType.Zero;
|
||||
value = FPZero(sign);
|
||||
|
||||
if ((valueBits & 0x007FFFFFu) != 0u)
|
||||
|
@ -1979,7 +1985,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
type = (~valueBits & 0x00400000u) == 0u ? FPType.QNaN : FPType.SNaN;
|
||||
type = (~valueBits & 0x00400000u) == 0u ? FPType.QNaN : FPType.SNaN;
|
||||
value = FPZero(sign);
|
||||
}
|
||||
}
|
||||
|
@ -2153,8 +2159,8 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
sign = (~valueBits & 0x8000000000000000ul) == 0u;
|
||||
|
||||
ulong exp64 = (valueBits & 0x7FF0000000000000ul) >> 52;
|
||||
ulong frac64 = valueBits & 0x000FFFFFFFFFFFFFul;
|
||||
ulong exp64 = (valueBits & 0x7FF0000000000000ul) >> 52;
|
||||
ulong frac64 = valueBits & 0x000FFFFFFFFFFFFFul;
|
||||
|
||||
double real;
|
||||
|
||||
|
@ -2223,8 +2229,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if (inf1 && inf2 && sign1 == !sign2)
|
||||
{
|
||||
|
@ -2265,8 +2273,8 @@ namespace ARMeilleure.Instructions
|
|||
ExecutionContext context = NativeInterface.GetContext();
|
||||
FPCR fpcr = context.Fpcr;
|
||||
|
||||
value1 = value1.FPUnpack(out FPType type1, out bool sign1, out _, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out bool sign2, out _, context, fpcr);
|
||||
value1 = value1.FPUnpack(out FPType type1, out _, out _, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out _, out _, context, fpcr);
|
||||
|
||||
int result;
|
||||
|
||||
|
@ -2420,8 +2428,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if ((inf1 && inf2) || (zero1 && zero2))
|
||||
{
|
||||
|
@ -2657,8 +2667,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if ((inf1 && zero2) || (zero1 && inf2))
|
||||
{
|
||||
|
@ -2701,11 +2713,13 @@ namespace ARMeilleure.Instructions
|
|||
FPCR fpcr = standardFpscr ? context.StandardFpcrValue : context.Fpcr;
|
||||
|
||||
valueA = valueA.FPUnpack(out FPType typeA, out bool signA, out ulong addend, context, fpcr);
|
||||
value1 = value1.FPUnpack(out FPType type1, out bool sign1, out ulong op1, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out bool sign2, out ulong op2, context, fpcr);
|
||||
value1 = value1.FPUnpack(out FPType type1, out bool sign1, out ulong op1, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out bool sign2, out ulong op2, context, fpcr);
|
||||
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
double result = FPProcessNaNs3(typeA, type1, type2, addend, op1, op2, out bool done, context, fpcr);
|
||||
|
||||
|
@ -2718,10 +2732,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool infA = typeA == FPType.Infinity; bool zeroA = typeA == FPType.Zero;
|
||||
bool infA = typeA == FPType.Infinity;
|
||||
bool zeroA = typeA == FPType.Zero;
|
||||
|
||||
bool signP = sign1 ^ sign2;
|
||||
bool infP = inf1 || inf2;
|
||||
bool signP = sign1 ^ sign2;
|
||||
bool infP = inf1 || inf2;
|
||||
bool zeroP = zero1 || zero2;
|
||||
|
||||
if ((inf1 && zero2) || (zero1 && inf2) || (infA && infP && signA != signP))
|
||||
|
@ -2784,8 +2799,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if ((inf1 && zero2) || (zero1 && inf2))
|
||||
{
|
||||
|
@ -2860,34 +2877,17 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else if (Math.Abs(value) < Math.Pow(2d, -1024))
|
||||
{
|
||||
bool overflowToInf;
|
||||
|
||||
switch (fpcr.GetRoundingMode())
|
||||
var overflowToInf = fpcr.GetRoundingMode() switch
|
||||
{
|
||||
case FPRoundingMode.ToNearest:
|
||||
overflowToInf = true;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsPlusInfinity:
|
||||
overflowToInf = !sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsMinusInfinity:
|
||||
overflowToInf = sign;
|
||||
break;
|
||||
|
||||
case FPRoundingMode.TowardsZero:
|
||||
overflowToInf = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Invalid rounding mode \"{fpcr.GetRoundingMode()}\".");
|
||||
}
|
||||
|
||||
FPRoundingMode.TowardsPlusInfinity => !sign,
|
||||
FPRoundingMode.TowardsMinusInfinity => sign,
|
||||
FPRoundingMode.TowardsZero => false,
|
||||
_ => throw new ArgumentException($"Invalid rounding mode \"{fpcr.GetRoundingMode()}\"."),
|
||||
};
|
||||
result = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign);
|
||||
|
||||
SoftFloat.FPProcessException(FPException.Overflow, context, fpcr);
|
||||
SoftFloat.FPProcessException(FPException.Inexact, context, fpcr);
|
||||
SoftFloat.FPProcessException(FPException.Inexact, context, fpcr);
|
||||
}
|
||||
else if ((fpcr & FPCR.Fz) != 0 && (Math.Abs(value) >= Math.Pow(2d, 1022)))
|
||||
{
|
||||
|
@ -2943,15 +2943,17 @@ namespace ARMeilleure.Instructions
|
|||
ExecutionContext context = NativeInterface.GetContext();
|
||||
FPCR fpcr = context.StandardFpcrValue;
|
||||
|
||||
value1 = value1.FPUnpack(out FPType type1, out bool sign1, out ulong op1, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out bool sign2, out ulong op2, context, fpcr);
|
||||
value1 = value1.FPUnpack(out FPType type1, out _, out ulong op1, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out _, out ulong op2, context, fpcr);
|
||||
|
||||
double result = FPProcessNaNs(type1, type2, op1, op2, out bool done, context, fpcr);
|
||||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
double product;
|
||||
|
||||
|
@ -2984,8 +2986,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if ((inf1 && zero2) || (zero1 && inf2))
|
||||
{
|
||||
|
@ -3116,8 +3120,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if (inf1 && inf2 && sign1 == sign2)
|
||||
{
|
||||
|
@ -3158,15 +3164,17 @@ namespace ARMeilleure.Instructions
|
|||
ExecutionContext context = NativeInterface.GetContext();
|
||||
FPCR fpcr = context.StandardFpcrValue;
|
||||
|
||||
value1 = value1.FPUnpack(out FPType type1, out bool sign1, out ulong op1, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out bool sign2, out ulong op2, context, fpcr);
|
||||
value1 = value1.FPUnpack(out FPType type1, out _, out ulong op1, context, fpcr);
|
||||
value2 = value2.FPUnpack(out FPType type2, out _, out ulong op2, context, fpcr);
|
||||
|
||||
double result = FPProcessNaNs(type1, type2, op1, op2, out bool done, context, fpcr);
|
||||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
double product;
|
||||
|
||||
|
@ -3199,8 +3207,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if ((inf1 && zero2) || (zero1 && inf2))
|
||||
{
|
||||
|
@ -3285,8 +3295,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (!done)
|
||||
{
|
||||
bool inf1 = type1 == FPType.Infinity; bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity; bool zero2 = type2 == FPType.Zero;
|
||||
bool inf1 = type1 == FPType.Infinity;
|
||||
bool zero1 = type1 == FPType.Zero;
|
||||
bool inf2 = type2 == FPType.Infinity;
|
||||
bool zero2 = type2 == FPType.Zero;
|
||||
|
||||
if (inf1 && inf2 && sign1 == sign2)
|
||||
{
|
||||
|
@ -3383,7 +3395,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if ((valueBits & 0x000FFFFFFFFFFFFFul) == 0ul || (fpcr & FPCR.Fz) != 0)
|
||||
{
|
||||
type = FPType.Zero;
|
||||
type = FPType.Zero;
|
||||
value = FPZero(sign);
|
||||
|
||||
if ((valueBits & 0x000FFFFFFFFFFFFFul) != 0ul)
|
||||
|
@ -3404,7 +3416,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
type = (~valueBits & 0x0008000000000000ul) == 0ul ? FPType.QNaN : FPType.SNaN;
|
||||
type = (~valueBits & 0x0008000000000000ul) == 0ul ? FPType.QNaN : FPType.SNaN;
|
||||
value = FPZero(sign);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue