Add missing Equals and GetHashCode overrides on some structs, misc small tweaks
This commit is contained in:
parent
316d2cdace
commit
df812038d4
4 changed files with 88 additions and 38 deletions
|
@ -36,8 +36,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
Add(Instruction.CompareLessUI, GenerateCompareLessUI);
|
Add(Instruction.CompareLessUI, GenerateCompareLessUI);
|
||||||
Add(Instruction.CompareNotEqual, GenerateCompareNotEqual);
|
Add(Instruction.CompareNotEqual, GenerateCompareNotEqual);
|
||||||
Add(Instruction.ConditionalSelect, GenerateConditionalSelect);
|
Add(Instruction.ConditionalSelect, GenerateConditionalSelect);
|
||||||
Add(Instruction.CountLeadingZeros, GenerateCountLeadingZeros);
|
|
||||||
Add(Instruction.Copy, GenerateCopy);
|
Add(Instruction.Copy, GenerateCopy);
|
||||||
|
Add(Instruction.CountLeadingZeros, GenerateCountLeadingZeros);
|
||||||
Add(Instruction.Divide, GenerateDivide);
|
Add(Instruction.Divide, GenerateDivide);
|
||||||
Add(Instruction.Fill, GenerateFill);
|
Add(Instruction.Fill, GenerateFill);
|
||||||
Add(Instruction.Load, GenerateLoad);
|
Add(Instruction.Load, GenerateLoad);
|
||||||
|
@ -229,34 +229,6 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
context.Assembler.Cmovcc(operation.Dest, operation.GetSource(1), X86Condition.NotEqual);
|
context.Assembler.Cmovcc(operation.Dest, operation.GetSource(1), X86Condition.NotEqual);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateCountLeadingZeros(CodeGenContext context, Operation operation)
|
|
||||||
{
|
|
||||||
Operand dest = operation.Dest;
|
|
||||||
|
|
||||||
Operand dest32 = Get32BitsRegister(dest.GetRegister());
|
|
||||||
|
|
||||||
context.Assembler.Bsr(dest, operation.GetSource(0));
|
|
||||||
|
|
||||||
int operandSize = dest.Type == OperandType.I32 ? 32 : 64;
|
|
||||||
int operandMask = operandSize - 1;
|
|
||||||
|
|
||||||
//When the input operand is 0, the result is undefined, however the
|
|
||||||
//ZF flag is set. We are supposed to return the operand size on that
|
|
||||||
//case. So, add an additional jump to handle that case, by moving the
|
|
||||||
//operand size constant to the destination register.
|
|
||||||
context.JumpToNear(X86Condition.NotEqual);
|
|
||||||
|
|
||||||
context.Assembler.Mov(dest32, new Operand(operandSize | operandMask));
|
|
||||||
|
|
||||||
context.JumpHere();
|
|
||||||
|
|
||||||
//BSR returns the zero based index of the last bit set on the operand,
|
|
||||||
//starting from the least significant bit. However we are supposed to
|
|
||||||
//return the number of 0 bits on the high end. So, we invert the result
|
|
||||||
//of the BSR using XOR to get the correct value.
|
|
||||||
context.Assembler.Xor(dest32, new Operand(operandMask));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void GenerateCopy(CodeGenContext context, Operation operation)
|
private static void GenerateCopy(CodeGenContext context, Operation operation)
|
||||||
{
|
{
|
||||||
Operand dest = operation.Dest;
|
Operand dest = operation.Dest;
|
||||||
|
@ -299,6 +271,34 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void GenerateCountLeadingZeros(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
Operand dest = operation.Dest;
|
||||||
|
|
||||||
|
Operand dest32 = Get32BitsRegister(dest.GetRegister());
|
||||||
|
|
||||||
|
context.Assembler.Bsr(dest, operation.GetSource(0));
|
||||||
|
|
||||||
|
int operandSize = dest.Type == OperandType.I32 ? 32 : 64;
|
||||||
|
int operandMask = operandSize - 1;
|
||||||
|
|
||||||
|
//When the input operand is 0, the result is undefined, however the
|
||||||
|
//ZF flag is set. We are supposed to return the operand size on that
|
||||||
|
//case. So, add an additional jump to handle that case, by moving the
|
||||||
|
//operand size constant to the destination register.
|
||||||
|
context.JumpToNear(X86Condition.NotEqual);
|
||||||
|
|
||||||
|
context.Assembler.Mov(dest32, new Operand(operandSize | operandMask));
|
||||||
|
|
||||||
|
context.JumpHere();
|
||||||
|
|
||||||
|
//BSR returns the zero based index of the last bit set on the operand,
|
||||||
|
//starting from the least significant bit. However we are supposed to
|
||||||
|
//return the number of 0 bits on the high end. So, we invert the result
|
||||||
|
//of the BSR using XOR to get the correct value.
|
||||||
|
context.Assembler.Xor(dest32, new Operand(operandMask));
|
||||||
|
}
|
||||||
|
|
||||||
private static void GenerateDivide(CodeGenContext context, Operation operation)
|
private static void GenerateDivide(CodeGenContext context, Operation operation)
|
||||||
{
|
{
|
||||||
Operand divisor = operation.GetSource(1);
|
Operand divisor = operation.GetSource(1);
|
||||||
|
|
|
@ -4,19 +4,19 @@ namespace ARMeilleure.Common
|
||||||
{
|
{
|
||||||
static class BitUtils
|
static class BitUtils
|
||||||
{
|
{
|
||||||
private const int deBrujinSequence = 0x77cb531;
|
private const int DeBrujinSequence = 0x77cb531;
|
||||||
|
|
||||||
private static int[] deBrujinLbsLut;
|
private static int[] DeBrujinLbsLut;
|
||||||
|
|
||||||
static BitUtils()
|
static BitUtils()
|
||||||
{
|
{
|
||||||
deBrujinLbsLut = new int[32];
|
DeBrujinLbsLut = new int[32];
|
||||||
|
|
||||||
for (int index = 0; index < deBrujinLbsLut.Length; index++)
|
for (int index = 0; index < DeBrujinLbsLut.Length; index++)
|
||||||
{
|
{
|
||||||
uint lutIndex = (uint)(deBrujinSequence * (1 << index)) >> 27;
|
uint lutIndex = (uint)(DeBrujinSequence * (1 << index)) >> 27;
|
||||||
|
|
||||||
deBrujinLbsLut[lutIndex] = index;
|
DeBrujinLbsLut[lutIndex] = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ namespace ARMeilleure.Common
|
||||||
|
|
||||||
int lsb = value & -value;
|
int lsb = value & -value;
|
||||||
|
|
||||||
return deBrujinLbsLut[(uint)(deBrujinSequence * lsb) >> 27];
|
return DeBrujinLbsLut[(uint)(DeBrujinSequence * lsb) >> 27];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int HighestBitSet(int value)
|
public static int HighestBitSet(int value)
|
||||||
|
|
|
@ -2,7 +2,7 @@ using System;
|
||||||
|
|
||||||
namespace ARMeilleure.State
|
namespace ARMeilleure.State
|
||||||
{
|
{
|
||||||
public struct V128
|
public struct V128 : IEquatable<V128>
|
||||||
{
|
{
|
||||||
private ulong _e0;
|
private ulong _e0;
|
||||||
private ulong _e1;
|
private ulong _e1;
|
||||||
|
@ -71,5 +71,30 @@ namespace ARMeilleure.State
|
||||||
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(_e0, _e1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(V128 x, V128 y)
|
||||||
|
{
|
||||||
|
return x.Equals(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(V128 x, V128 y)
|
||||||
|
{
|
||||||
|
return !x.Equals(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj is V128 vector && Equals(vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(V128 other)
|
||||||
|
{
|
||||||
|
return other._e0 == _e0 && other._e1 == _e1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Tests.Unicorn
|
namespace Ryujinx.Tests.Unicorn
|
||||||
{
|
{
|
||||||
public struct SimdValue
|
public struct SimdValue : IEquatable<SimdValue>
|
||||||
{
|
{
|
||||||
private ulong _e0;
|
private ulong _e0;
|
||||||
private ulong _e1;
|
private ulong _e1;
|
||||||
|
@ -76,5 +76,30 @@ namespace Ryujinx.Tests.Unicorn
|
||||||
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(_e0, _e1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(SimdValue x, SimdValue y)
|
||||||
|
{
|
||||||
|
return x.Equals(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(SimdValue x, SimdValue y)
|
||||||
|
{
|
||||||
|
return !x.Equals(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj is SimdValue simdValue && Equals(simdValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(SimdValue other)
|
||||||
|
{
|
||||||
|
return other._e0 == _e0 && other._e1 == _e1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue