Implemented arm64 instructions: ldp and stp
This commit is contained in:
9
src/arm/Add.go
Normal file
9
src/arm/Add.go
Normal file
@ -0,0 +1,9 @@
|
||||
package arm
|
||||
|
||||
import "git.urbach.dev/cli/q/src/cpu"
|
||||
|
||||
// AddRegisterNumber adds a number to a register
|
||||
func AddRegisterNumber(destination cpu.Register, source cpu.Register, number int) uint32 {
|
||||
number &= 0xFFF
|
||||
return 0b100100010<<23 | (uint32(number) << 10) | (uint32(source) << 5) | uint32(destination)
|
||||
}
|
12
src/arm/LoadPair.go
Normal file
12
src/arm/LoadPair.go
Normal file
@ -0,0 +1,12 @@
|
||||
package arm
|
||||
|
||||
import "git.urbach.dev/cli/q/src/cpu"
|
||||
|
||||
// LoadPair calculates an address from a base register value and an immediate offset,
|
||||
// loads two 64-bit doublewords from memory, and writes them to two registers.
|
||||
// This is the post-index version of the instruction so the offset is applied to the base register after the memory access.
|
||||
func LoadPair(reg1 cpu.Register, reg2 cpu.Register, base cpu.Register, offset int) uint32 {
|
||||
offset /= 8
|
||||
offset &= 0b1111111
|
||||
return 0b1010100011<<22 | (uint32(offset) << 15) | (uint32(reg2) << 10) | (uint32(base) << 5) | uint32(reg1)
|
||||
}
|
28
src/arm/LoadPair_test.go
Normal file
28
src/arm/LoadPair_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
package arm_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.urbach.dev/cli/q/src/arm"
|
||||
"git.urbach.dev/cli/q/src/cpu"
|
||||
"git.urbach.dev/go/assert"
|
||||
)
|
||||
|
||||
func TestLoadPair(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Reg1 cpu.Register
|
||||
Reg2 cpu.Register
|
||||
Base cpu.Register
|
||||
Offset int
|
||||
Code uint32
|
||||
}{
|
||||
{arm.FP, arm.LR, arm.SP, 32, 0xA8C27BFD},
|
||||
{arm.FP, arm.LR, arm.SP, 16, 0xA8C17BFD},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("ldp %s, %s, [%s], #%d", pattern.Reg1, pattern.Reg2, pattern.Base, pattern.Offset)
|
||||
code := arm.LoadPair(pattern.Reg1, pattern.Reg2, pattern.Base, pattern.Offset)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
@ -6,6 +6,10 @@ import (
|
||||
|
||||
// MoveRegisterRegister copies a register to another register.
|
||||
func MoveRegisterRegister(destination cpu.Register, source cpu.Register) uint32 {
|
||||
if source == SP || destination == SP {
|
||||
return AddRegisterNumber(destination, source, 0)
|
||||
}
|
||||
|
||||
return 0b10101010<<24 | uint32(source)<<16 | 0b11111<<5 | uint32(destination)
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@ func TestMoveRegisterRegister(t *testing.T) {
|
||||
}{
|
||||
{arm.X0, arm.X1, 0xAA0103E0},
|
||||
{arm.X1, arm.X0, 0xAA0003E1},
|
||||
{arm.FP, arm.SP, 0x910003FD},
|
||||
{arm.SP, arm.FP, 0x910003BF},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
|
14
src/arm/StorePair.go
Normal file
14
src/arm/StorePair.go
Normal file
@ -0,0 +1,14 @@
|
||||
package arm
|
||||
|
||||
import (
|
||||
"git.urbach.dev/cli/q/src/cpu"
|
||||
)
|
||||
|
||||
// StorePair calculates an address from a base register value and an immediate offset multiplied by 8,
|
||||
// and stores the values of two registers to the calculated address.
|
||||
// This is the pre-index version of the instruction so the offset is applied to the base register before the memory access.
|
||||
func StorePair(reg1 cpu.Register, reg2 cpu.Register, base cpu.Register, offset int) uint32 {
|
||||
offset /= 8
|
||||
offset &= 0b1111111
|
||||
return 0b1010100110<<22 | uint32(offset)<<15 | uint32(reg2)<<10 | uint32(base)<<5 | uint32(reg1)
|
||||
}
|
28
src/arm/StorePair_test.go
Normal file
28
src/arm/StorePair_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
package arm_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.urbach.dev/cli/q/src/arm"
|
||||
"git.urbach.dev/cli/q/src/cpu"
|
||||
"git.urbach.dev/go/assert"
|
||||
)
|
||||
|
||||
func TestStorePair(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Reg1 cpu.Register
|
||||
Reg2 cpu.Register
|
||||
Base cpu.Register
|
||||
Offset int
|
||||
Code uint32
|
||||
}{
|
||||
{arm.FP, arm.LR, arm.SP, -32, 0xA9BE7BFD},
|
||||
{arm.FP, arm.LR, arm.SP, -16, 0xA9BF7BFD},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("stp %s, %s, [%s, #%d]!", pattern.Reg1, pattern.Reg2, pattern.Base, pattern.Offset)
|
||||
code := arm.StorePair(pattern.Reg1, pattern.Reg2, pattern.Base, pattern.Offset)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user