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.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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue