diff --git a/src/RP2040.Core/Cpu/Instructions/BitOps.cs b/src/RP2040.Core/Cpu/Instructions/BitOps.cs index 41df678..67d4866 100644 --- a/src/RP2040.Core/Cpu/Instructions/BitOps.cs +++ b/src/RP2040.Core/Cpu/Instructions/BitOps.cs @@ -185,10 +185,11 @@ public static void MovRegister(ushort opcode, CortexM0Plus cpu) public static void Movs(ushort opcode, CortexM0Plus cpu) { var value = (uint)(opcode & 0xFF); + var rd = (opcode >> 8) & 7; - cpu.Registers[(opcode >> 8) & 7] = value; + cpu.Registers[rd] = value; - cpu.Registers.N = false; + cpu.Registers.N = (int)value < 0; cpu.Registers.Z = value == 0; } diff --git a/tests/RP2040.Core.Tests/Cpu/Instructions/BitOpsTests.cs b/tests/RP2040.Core.Tests/Cpu/Instructions/BitOpsTests.cs index 3cb2c8a..7ab7470 100644 --- a/tests/RP2040.Core.Tests/Cpu/Instructions/BitOpsTests.cs +++ b/tests/RP2040.Core.Tests/Cpu/Instructions/BitOpsTests.cs @@ -351,6 +351,70 @@ public void Should_LoadImmediateValue_And_UpdateFlags() Cpu.Registers[R5].Should().Be(128); Cpu.Registers.PC.Should().Be(0x20000002); } + + [Fact] + public void Should_ClearLowerTwoBits_When_WritingToStackPointer() + { + // Arrange + var opcode = InstructionEmiter.Mov(SP, R5); + Bus.WriteHalfWord(0x20000000, opcode); + + Cpu.Registers[R5] = 0x53; + + // Act + Cpu.Step(); + + // Assert + Cpu.Registers.SP.Should().Be(0x50); + } + + [Fact] + public void Should_ClearLeastSignificantBit_When_WritingToProgramCounter() + { + // Arrange + var opcode = InstructionEmiter.Mov(PC, R5); + Bus.WriteHalfWord(0x20000000, opcode); + + Cpu.Registers[R5] = 0x53; + + // Act + Cpu.Step(); + + // Assert + Cpu.Registers.PC.Should().Be(0x52); + } + + [Fact] + public void Should_CopyValue_BetweenRegisters() + { + // Arrange + var opcode = InstructionEmiter.Mov(R6, R5); + Bus.WriteHalfWord(0x20000000, opcode); + + Cpu.Registers[R5] = 50; + + // Act + Cpu.Step(); + + // Assert + Cpu.Registers[R6].Should().Be(50); + } + + [Fact] + public void Should_CopyNegativeValue_BetweenRegisters() + { + // Arrange + var opcode = InstructionEmiter.Mov(R6, R5); + Bus.WriteHalfWord(0x20000000, opcode); + + Cpu.Registers[R5] = unchecked((uint)-50); + + // Act + Cpu.Step(); + + // Assert + Cpu.Registers[R6].Should().Be(unchecked((uint)-50)); + } } public class Mvns : CpuTestBase