Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 36 additions & 10 deletions src/Core/Echo/Memory/BitVectorSpan.Integer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -609,8 +609,9 @@ private Trilean IntegerMultiplyLle(BitVectorSpan other)
/// Interprets the bit vector as an integer and divides it by a second integer.
/// </summary>
/// <param name="other">The integer to divide the current integer by.</param>
/// <param name="signed">Indicates whether the integers should be interpreted as signed or unsigned integers.</param>
/// <exception cref="ArgumentException">Occurs when the sizes of the integers do not match in bit length.</exception>
public void IntegerDivide(BitVectorSpan other)
public void IntegerDivide(BitVectorSpan other, bool signed)
{
AssertSameBitSize(other);

Expand All @@ -624,19 +625,31 @@ public void IntegerDivide(BitVectorSpan other)
switch (Count)
{
case 8:
U8 /= other.U8;
if (signed)
I8 /= other.I8;
else
U8 /= other.U8;
return;

case 16:
U16 /= other.U16;
if (signed)
I16 /= other.I16;
else
U16 /= other.U16;
return;

case 32:
U32 /= other.U32;
if (signed)
I32 /= other.I32;
else
U32 /= other.U32;
return;

case 64:
U64 /= other.U64;
if (signed)
I64 /= other.I64;
else
U64 /= other.U64;
return;

default:
Expand All @@ -650,8 +663,9 @@ public void IntegerDivide(BitVectorSpan other)
/// Interprets the bit vector as an integer, divides it by a second integer and produces the remainder.
/// </summary>
/// <param name="other">The integer to divide the current integer by.</param>
/// <param name="signed">Indicates whether the integers should be interpreted as signed or unsigned integers.</param>
/// <exception cref="ArgumentException">Occurs when the sizes of the integers do not match in bit length.</exception>
public void IntegerRemainder(BitVectorSpan other)
public void IntegerRemainder(BitVectorSpan other, bool signed)
{
AssertSameBitSize(other);

Expand All @@ -665,19 +679,31 @@ public void IntegerRemainder(BitVectorSpan other)
switch (Count)
{
case 8:
U8 %= other.U8;
if (signed)
I8 %= other.I8;
else
U8 %= other.U8;
return;

case 16:
U16 %= other.U16;
if (signed)
I16 %= other.I16;
else
U16 %= other.U16;
return;

case 32:
U32 %= other.U32;
if (signed)
I32 %= other.I32;
else
U32 %= other.U32;
return;

case 64:
U64 %= other.U64;
if (signed)
I64 %= other.I64;
else
U64 %= other.U64;
return;

default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ protected override CilDispatchResult Evaluate(CilExecutionContext context, CilIn
var argument2Value = argument2.Contents.AsSpan();

if (argument1.TypeHint == StackSlotTypeHint.Integer)
argument1Value.IntegerDivide(argument2Value);
argument1Value.IntegerDivide(argument2Value, IsSignedOperation(instruction));
else
argument1Value.FloatDivide(argument2Value);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ protected override CilDispatchResult Evaluate(
var argument2Value = argument2.Contents.AsSpan();

if (argument1.TypeHint == StackSlotTypeHint.Integer)
argument1Value.IntegerRemainder(argument2Value);
argument1Value.IntegerRemainder(argument2Value, IsSignedOperation(instruction));
else
argument1Value.FloatRemainder(argument2Value);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,21 @@ protected void AssertCorrect(CilOpCode code, ulong a, ulong b, ulong expected)
Assert.Equal(64, slot.Contents.Count);
Assert.Equal(expected, slot.Contents.AsSpan().U64);
}

protected void AssertCorrect(CilOpCode code, long a, long b, long expected)
{
var stack = Context.CurrentFrame.EvaluationStack;

stack.Push(new StackSlot(a, StackSlotTypeHint.Integer));
stack.Push(new StackSlot(b, StackSlotTypeHint.Integer));

var result = Dispatcher.Dispatch(Context, new CilInstruction(code));

Assert.True(result.IsSuccess);
var slot = Context.CurrentFrame.EvaluationStack.Peek();
Assert.Equal(64, slot.Contents.Count);
Assert.Equal(expected, slot.Contents.AsSpan().I64);
}

protected void AssertCorrect(CilOpCode code, double a, double b, double expected)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using AsmResolver.PE.DotNet.Cil;
using Echo.Platforms.AsmResolver.Emulation;
using Echo.Platforms.AsmResolver.Emulation.Stack;
using Echo.Platforms.AsmResolver.Tests.Mock;
using Xunit;
Expand All @@ -15,18 +14,18 @@ public DivHandlerTest(MockModuleFixture fixture)
}

[Fact]
public void DivI4ToI4() => AssertCorrect(CilOpCodes.Div, 1000u, 20u, 50u);
public void DivI4ToI4() => AssertCorrect(CilOpCodes.Div, -1000, 20, -50);

[Theory]
[InlineData(1000u, 20ul, 50ul)]
public void DivI4ToI8(uint a, ulong b, ulong expected) => AssertCorrect(CilOpCodes.Div, a, b, expected);
public void DivU4ToU8(uint a, ulong b, ulong expected) => AssertCorrect(CilOpCodes.Div_Un, a, b, expected);

[Theory]
[InlineData(1000ul, 20u, 50ul)]
public void DivI8ToI4(ulong a, uint b, ulong expected) => AssertCorrect(CilOpCodes.Div, a, b, expected);
public void DivI8ToI4(ulong a, uint b, ulong expected) => AssertCorrect(CilOpCodes.Div_Un, a, b, expected);

[Fact]
public void DivI8ToI8() => AssertCorrect(CilOpCodes.Div, 1000ul, 20ul, 50ul);
public void DivI8ToI8() => AssertCorrect(CilOpCodes.Div, -1000L, 20L, -50L);
Comment thread
Washi1337 marked this conversation as resolved.
Outdated

[Fact]
public void DivR8ToR8() => AssertCorrect(CilOpCodes.Div, 1000.0, 20.0, 50.0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,30 @@ public RemHandlerTest(MockModuleFixture fixture)
{
}

[Theory]
[InlineData(-1000, 20, 0)]
[InlineData(-1000, 999, -1)]
public void I4ToI4(int a, int b, int expected) => AssertCorrect(CilOpCodes.Rem, a, b, expected);

[Theory]
[InlineData(1000u, 20u, 0u)]
[InlineData(1000u, 999u, 1u)]
public void I4ToI4(uint a, uint b, uint expected) => AssertCorrect(CilOpCodes.Rem, a, b, expected);

public void U4ToU4(uint a, uint b, uint expected) => AssertCorrect(CilOpCodes.Rem_Un, a, b, expected);
[Theory]
[InlineData(1000u, 20ul, 0ul)]
[InlineData(1000u, 999ul, 1ul)]
public void I4ToI8(uint a, ulong b, ulong expected) => AssertCorrect(CilOpCodes.Rem, a, b, expected);
[InlineData(-1000, 20L, 0L)]
[InlineData(-1000, 999L, -1L)]
public void I4ToI8(int a, long b, long expected) => AssertCorrect(CilOpCodes.Rem, a, b, expected);

[Theory]
[InlineData(1000ul, 20u, 0ul)]
[InlineData(1000ul, 999u, 1ul)]
public void I8ToI4(ulong a, uint b, ulong expected) => AssertCorrect(CilOpCodes.Rem, a, b, expected);
[InlineData(-1000L, 20, 0L)]
[InlineData(-1000L, 999, -1L)]
public void I8ToI4(long a, int b, long expected) => AssertCorrect(CilOpCodes.Rem, a, b, expected);

[Theory]
[InlineData(1000ul, 20ul, 0ul)]
[InlineData(1000ul, 999ul, 1ul)]
public void I8ToI8(ulong a, ulong b, ulong expected) => AssertCorrect(CilOpCodes.Rem, a, b, expected);
[InlineData(-1000L, 20ul, 0L)]
[InlineData(-1000L, 999ul, -1L)]
public void I8ToI8(long a, long b, long expected) => AssertCorrect(CilOpCodes.Rem, a, b, expected);

[Theory]
[InlineData(1000.0, 20.0, 1000.0 % 20.0)]
Expand Down