Fixed move with negative numbers on arm64
This commit is contained in:
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user