Add missing Equals and GetHashCode overrides on some structs, misc small tweaks

This commit is contained in:
gdkchan 2019-05-29 15:56:24 -03:00
parent 316d2cdace
commit df812038d4
4 changed files with 88 additions and 38 deletions

View file

@ -36,8 +36,8 @@ namespace ARMeilleure.CodeGen.X86
Add(Instruction.CompareLessUI, GenerateCompareLessUI);
Add(Instruction.CompareNotEqual, GenerateCompareNotEqual);
Add(Instruction.ConditionalSelect, GenerateConditionalSelect);
Add(Instruction.CountLeadingZeros, GenerateCountLeadingZeros);
Add(Instruction.Copy, GenerateCopy);
Add(Instruction.CountLeadingZeros, GenerateCountLeadingZeros);
Add(Instruction.Divide, GenerateDivide);
Add(Instruction.Fill, GenerateFill);
Add(Instruction.Load, GenerateLoad);
@ -229,34 +229,6 @@ namespace ARMeilleure.CodeGen.X86
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)
{
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)
{
Operand divisor = operation.GetSource(1);

View file

@ -4,19 +4,19 @@ namespace ARMeilleure.Common
{
static class BitUtils
{
private const int deBrujinSequence = 0x77cb531;
private const int DeBrujinSequence = 0x77cb531;
private static int[] deBrujinLbsLut;
private static int[] DeBrujinLbsLut;
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;
return deBrujinLbsLut[(uint)(deBrujinSequence * lsb) >> 27];
return DeBrujinLbsLut[(uint)(DeBrujinSequence * lsb) >> 27];
}
public static int HighestBitSet(int value)

View file

@ -2,7 +2,7 @@ using System;
namespace ARMeilleure.State
{
public struct V128
public struct V128 : IEquatable<V128>
{
private ulong _e0;
private ulong _e1;
@ -71,5 +71,30 @@ namespace ARMeilleure.State
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;
}
}
}

View file

@ -2,7 +2,7 @@ using System;
namespace Ryujinx.Tests.Unicorn
{
public struct SimdValue
public struct SimdValue : IEquatable<SimdValue>
{
private ulong _e0;
private ulong _e1;
@ -76,5 +76,30 @@ namespace Ryujinx.Tests.Unicorn
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;
}
}
}