[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:
TSRBerry 2023-06-26 07:25:06 +02:00 committed by GitHub
parent 2de78a2d55
commit ff53dcf560
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
300 changed files with 3515 additions and 3120 deletions

View file

@ -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++)

View file

@ -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)

View file

@ -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)

View file

@ -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);

View file

@ -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));
}
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -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);

View file

@ -52,4 +52,4 @@ namespace ARMeilleure.Instructions
context.Return(Const(op.Address));
}
}
}
}

View file

@ -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
}
}
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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
}
}
}
}
}

View file

@ -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));
}
}
}
}

View file

@ -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();
}
}
}
}

View file

@ -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

View file

@ -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)
{

View file

@ -38,4 +38,4 @@ namespace ARMeilleure.Instructions
SetIntOrZR(context, op.Rd, Const(op.GetOperandType(), op.Immediate));
}
}
}
}

View file

@ -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);
}
}
}
}

View file

@ -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);

View file

@ -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));

View file

@ -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)
{

View file

@ -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))
{

View file

@ -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);
}

View file

@ -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);

View file

@ -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
}
}

View file

@ -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
}
}

View file

@ -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);
}
}
}
}

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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
}
}
}
}
}

View file

@ -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));
}
}
}
}

View file

@ -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)

View file

@ -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);

View file

@ -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));
}
}
}
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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)

View file

@ -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)
{

View file

@ -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++)
{

View file

@ -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

View file

@ -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;
}
}
}
}

View file

@ -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++)
{

View file

@ -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);
}
}