Fixed move with negative numbers on arm64

This commit is contained in:
2025-03-14 11:58:36 +01:00
parent 9410287605
commit 1d0e49f0e3
3 changed files with 45 additions and 5 deletions

View File

@ -15,9 +15,18 @@ func MoveRegisterRegister(destination cpu.Register, source cpu.Register) uint32
// MoveRegisterNumber moves an integer into the given register.
func MoveRegisterNumber(destination cpu.Register, number int) uint32 {
if number < 0 {
return MoveInvertedWideImmediate(destination, ^number)
}
return MoveZero(destination, 0, uint16(number))
}
// MoveInvertedWideImmediate moves an inverted 16-bit immediate value to a register.
func MoveInvertedWideImmediate(destination cpu.Register, number int) uint32 {
return 0b100100101<<23 | regImm(destination, number)
}
// MoveKeep moves a 16-bit integer into the given register and keeps all other bits.
func MoveKeep(destination cpu.Register, halfword int, number uint16) uint32 {
return mov(0b11, halfword, number, destination)

View File

@ -27,6 +27,24 @@ func TestMoveRegisterRegister(t *testing.T) {
}
}
func TestMoveRegisterNumber(t *testing.T) {
usagePatterns := []struct {
Register cpu.Register
Number int
Code uint32
}{
{arm.X0, 0, 0xD2800000},
{arm.X0, 1, 0xD2800020},
{arm.X0, -1, 0x92800000},
}
for _, pattern := range usagePatterns {
t.Logf("mov %s, %d", pattern.Register, pattern.Number)
code := arm.MoveRegisterNumber(pattern.Register, pattern.Number)
assert.DeepEqual(t, code, pattern.Code)
}
}
func TestMoveKeep(t *testing.T) {
usagePatterns := []struct {
Register cpu.Register
@ -38,7 +56,7 @@ func TestMoveKeep(t *testing.T) {
}
for _, pattern := range usagePatterns {
t.Logf("movk %s, %x", pattern.Register, pattern.Number)
t.Logf("movk %s, %d", pattern.Register, pattern.Number)
code := arm.MoveKeep(pattern.Register, 0, pattern.Number)
assert.DeepEqual(t, code, pattern.Code)
}
@ -55,7 +73,7 @@ func TestMoveZero(t *testing.T) {
}
for _, pattern := range usagePatterns {
t.Logf("movz %s, %x", pattern.Register, pattern.Number)
t.Logf("movz %s, %d", pattern.Register, pattern.Number)
code := arm.MoveZero(pattern.Register, 0, pattern.Number)
assert.DeepEqual(t, code, pattern.Code)
}

View File

@ -2,19 +2,32 @@ package arm
import "git.urbach.dev/cli/q/src/cpu"
const (
mask6 = 0b111111
mask7 = 0b1111111
mask9 = 0b1_11111111
mask12 = 0b1111_11111111
mask16 = 0b11111111_11111111
)
// memory encodes an instruction with a register, a base register and an offset.
func memory(destination cpu.Register, base cpu.Register, imm9 int) uint32 {
return uint32(imm9&0b1_1111_1111)<<12 | uint32(base)<<5 | uint32(destination)
return uint32(imm9&mask9)<<12 | uint32(base)<<5 | uint32(destination)
}
// pair encodes an instruction using a register pair with memory.
func pair(reg1 cpu.Register, reg2 cpu.Register, base cpu.Register, imm7 int) uint32 {
return uint32(imm7&0b111_1111)<<15 | uint32(reg2)<<10 | uint32(base)<<5 | uint32(reg1)
return uint32(imm7&mask7)<<15 | uint32(reg2)<<10 | uint32(base)<<5 | uint32(reg1)
}
// regImm encodes an instruction with a register and an immediate.
func regImm(d cpu.Register, imm16 int) uint32 {
return uint32(imm16&mask16)<<5 | uint32(d)
}
// reg2imm encodes an instruction with 2 registers and an immediate.
func reg2imm(d cpu.Register, n cpu.Register, imm12 int) uint32 {
return uint32(imm12&0b1111_1111_1111)<<10 | uint32(n)<<5 | uint32(d)
return uint32(imm12&mask12)<<10 | uint32(n)<<5 | uint32(d)
}
// reg3 encodes an instruction with 3 registers.