Refactored arm package
This commit is contained in:
@ -23,7 +23,7 @@ func TestAddRegisterNumber(t *testing.T) {
|
|||||||
t.Logf("add %s, %s, %d", pattern.Destination, pattern.Source, pattern.Number)
|
t.Logf("add %s, %s, %d", pattern.Destination, pattern.Source, pattern.Number)
|
||||||
code, encodable := arm.AddRegisterNumber(pattern.Destination, pattern.Source, pattern.Number)
|
code, encodable := arm.AddRegisterNumber(pattern.Destination, pattern.Source, pattern.Number)
|
||||||
assert.True(t, encodable)
|
assert.True(t, encodable)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +40,6 @@ func TestAddRegisterRegister(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("add %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
t.Logf("add %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
code := arm.AddRegisterRegister(pattern.Destination, pattern.Source, pattern.Operand)
|
code := arm.AddRegisterRegister(pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ func TestAndRegisterNumber(t *testing.T) {
|
|||||||
t.Logf("and %s, %s, %d", pattern.Destination, pattern.Source, pattern.Number)
|
t.Logf("and %s, %s, %d", pattern.Destination, pattern.Source, pattern.Number)
|
||||||
code, encodable := arm.AndRegisterNumber(pattern.Destination, pattern.Source, pattern.Number)
|
code, encodable := arm.AndRegisterNumber(pattern.Destination, pattern.Source, pattern.Number)
|
||||||
assert.True(t, encodable)
|
assert.True(t, encodable)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +44,6 @@ func TestAndRegisterRegister(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("and %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
t.Logf("and %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
code := arm.AndRegisterRegister(pattern.Destination, pattern.Source, pattern.Operand)
|
code := arm.AndRegisterRegister(pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,6 @@ package arm
|
|||||||
// Call branches to a PC-relative offset, setting the register X30 to PC+4.
|
// Call branches to a PC-relative offset, setting the register X30 to PC+4.
|
||||||
// The offset starts from the address of this instruction and is encoded as "imm26" times 4.
|
// The offset starts from the address of this instruction and is encoded as "imm26" times 4.
|
||||||
// This instruction is also known as BL (branch with link).
|
// This instruction is also known as BL (branch with link).
|
||||||
func Call(offset uint32) uint32 {
|
func Call(offset int) uint32 {
|
||||||
return uint32(0b100101<<26) | offset
|
return uint32(0b100101<<26) | uint32(offset&mask26)
|
||||||
}
|
}
|
||||||
|
25
src/arm/Call_test.go
Normal file
25
src/arm/Call_test.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package arm_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.urbach.dev/cli/q/src/arm"
|
||||||
|
"git.urbach.dev/go/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCall(t *testing.T) {
|
||||||
|
usagePatterns := []struct {
|
||||||
|
Offset int
|
||||||
|
Code uint32
|
||||||
|
}{
|
||||||
|
{0, 0x94000000},
|
||||||
|
{1, 0x94000001},
|
||||||
|
{-1, 0x97FFFFFF},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pattern := range usagePatterns {
|
||||||
|
t.Logf("bl %d", pattern.Offset)
|
||||||
|
code := arm.Call(pattern.Offset)
|
||||||
|
assert.Equal(t, code, pattern.Code)
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,7 @@ func TestCompareRegisterNumber(t *testing.T) {
|
|||||||
t.Logf("cmp %s, %d", pattern.Source, pattern.Number)
|
t.Logf("cmp %s, %d", pattern.Source, pattern.Number)
|
||||||
code, encodable := arm.CompareRegisterNumber(pattern.Source, pattern.Number)
|
code, encodable := arm.CompareRegisterNumber(pattern.Source, pattern.Number)
|
||||||
assert.True(t, encodable)
|
assert.True(t, encodable)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +40,6 @@ func TestCompareRegisterRegister(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("cmp %s, %s", pattern.Left, pattern.Right)
|
t.Logf("cmp %s, %s", pattern.Left, pattern.Right)
|
||||||
code := arm.CompareRegisterRegister(pattern.Left, pattern.Right)
|
code := arm.CompareRegisterRegister(pattern.Left, pattern.Right)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,6 @@ func TestDivSigned(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("sdiv %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
t.Logf("sdiv %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
code := arm.DivSigned(pattern.Destination, pattern.Source, pattern.Operand)
|
code := arm.DivSigned(pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,42 +2,40 @@ package arm
|
|||||||
|
|
||||||
// Jump continues program flow at the new offset.
|
// Jump continues program flow at the new offset.
|
||||||
func Jump(offset int) uint32 {
|
func Jump(offset int) uint32 {
|
||||||
offset &= 0b11_1111_1111_1111_1111_1111_1111
|
return 0b000101<<26 | uint32(offset&mask26)
|
||||||
return 0b000101<<26 | uint32(offset)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpIfEqual jumps if the result was equal.
|
// JumpIfEqual jumps if the result was equal.
|
||||||
func JumpIfEqual(offset int) uint32 {
|
func JumpIfEqual(offset int) uint32 {
|
||||||
return branchCond(0b0000, offset)
|
return branchCond(EQ, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpIfNotEqual jumps if the result was not equal.
|
// JumpIfNotEqual jumps if the result was not equal.
|
||||||
func JumpIfNotEqual(offset int) uint32 {
|
func JumpIfNotEqual(offset int) uint32 {
|
||||||
return branchCond(0b0001, offset)
|
return branchCond(NE, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpIfGreater jumps if the result was greater.
|
// JumpIfGreater jumps if the result was greater.
|
||||||
func JumpIfGreater(offset int) uint32 {
|
func JumpIfGreater(offset int) uint32 {
|
||||||
return branchCond(0b1100, offset)
|
return branchCond(GT, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpIfGreaterOrEqual jumps if the result was greater or equal.
|
// JumpIfGreaterOrEqual jumps if the result was greater or equal.
|
||||||
func JumpIfGreaterOrEqual(offset int) uint32 {
|
func JumpIfGreaterOrEqual(offset int) uint32 {
|
||||||
return branchCond(0b1010, offset)
|
return branchCond(GE, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpIfLess jumps if the result was less.
|
// JumpIfLess jumps if the result was less.
|
||||||
func JumpIfLess(offset int) uint32 {
|
func JumpIfLess(offset int) uint32 {
|
||||||
return branchCond(0b1001, offset)
|
return branchCond(LS, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// JumpIfLessOrEqual jumps if the result was less or equal.
|
// JumpIfLessOrEqual jumps if the result was less or equal.
|
||||||
func JumpIfLessOrEqual(offset int) uint32 {
|
func JumpIfLessOrEqual(offset int) uint32 {
|
||||||
return branchCond(0b1101, offset)
|
return branchCond(LE, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// branchCond performs a conditional branch to a PC-relative offset.
|
// branchCond performs a conditional branch to a PC-relative offset.
|
||||||
func branchCond(cond uint32, offset int) uint32 {
|
func branchCond(cond condition, imm19 int) uint32 {
|
||||||
offset &= 0b111_1111_1111_1111_1111
|
return 0b01010100<<24 | uint32(imm19&mask19)<<5 | uint32(cond)
|
||||||
return 0b01010100<<24 | uint32(offset)<<5 | cond
|
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,6 @@ func TestJump(t *testing.T) {
|
|||||||
code = arm.JumpIfLessOrEqual(pattern.Offset)
|
code = arm.JumpIfLessOrEqual(pattern.Offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,6 @@ func TestLoadAddress(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("adr %s, %d", pattern.Destination, pattern.Number)
|
t.Logf("adr %s, %d", pattern.Destination, pattern.Number)
|
||||||
code := arm.LoadAddress(pattern.Destination, pattern.Number)
|
code := arm.LoadAddress(pattern.Destination, pattern.Number)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,6 @@ func TestLoadPair(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("ldp %s, %s, [%s], #%d", pattern.Reg1, pattern.Reg2, pattern.Base, pattern.Offset)
|
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)
|
code := arm.LoadPair(pattern.Reg1, pattern.Reg2, pattern.Base, pattern.Offset)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,6 @@ func TestLoadRegister(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("ldur %s, [%s, %d] %db", pattern.Destination, pattern.Base, pattern.Offset, pattern.Length)
|
t.Logf("ldur %s, [%s, %d] %db", pattern.Destination, pattern.Base, pattern.Offset, pattern.Length)
|
||||||
code := arm.LoadRegister(pattern.Destination, pattern.Base, pattern.Offset, pattern.Length)
|
code := arm.LoadRegister(pattern.Destination, pattern.Base, pattern.Offset, pattern.Length)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ func TestMoveRegisterRegister(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("mov %s, %s", pattern.Destination, pattern.Source)
|
t.Logf("mov %s, %s", pattern.Destination, pattern.Source)
|
||||||
code := arm.MoveRegisterRegister(pattern.Destination, pattern.Source)
|
code := arm.MoveRegisterRegister(pattern.Destination, pattern.Source)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ func TestMoveRegisterNumberSI(t *testing.T) {
|
|||||||
|
|
||||||
if pattern.Code != 0 {
|
if pattern.Code != 0 {
|
||||||
assert.True(t, encodable)
|
assert.True(t, encodable)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
} else {
|
} else {
|
||||||
assert.False(t, encodable)
|
assert.False(t, encodable)
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ func TestMoveKeep(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("movk %s, %d", pattern.Register, pattern.Number)
|
t.Logf("movk %s, %d", pattern.Register, pattern.Number)
|
||||||
code := arm.MoveKeep(pattern.Register, 0, pattern.Number)
|
code := arm.MoveKeep(pattern.Register, 0, pattern.Number)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,6 +116,6 @@ func TestMoveZero(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("movz %s, %d", pattern.Register, pattern.Number)
|
t.Logf("movz %s, %d", pattern.Register, pattern.Number)
|
||||||
code := arm.MoveZero(pattern.Register, 0, pattern.Number)
|
code := arm.MoveZero(pattern.Register, 0, pattern.Number)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ func TestMulRegisterRegister(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("mul %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
t.Logf("mul %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
code := arm.MulRegisterRegister(pattern.Destination, pattern.Source, pattern.Operand)
|
code := arm.MulRegisterRegister(pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +40,6 @@ func TestMultiplySubtract(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("msub %s, %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand, pattern.Extra)
|
t.Logf("msub %s, %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand, pattern.Extra)
|
||||||
code := arm.MultiplySubtract(pattern.Destination, pattern.Source, pattern.Operand, pattern.Extra)
|
code := arm.MultiplySubtract(pattern.Destination, pattern.Source, pattern.Operand, pattern.Extra)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,6 @@ func TestNegateRegister(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("neg %s, %s", pattern.Destination, pattern.Source)
|
t.Logf("neg %s, %s", pattern.Destination, pattern.Source)
|
||||||
code := arm.NegateRegister(pattern.Destination, pattern.Source)
|
code := arm.NegateRegister(pattern.Destination, pattern.Source)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ func TestOrRegisterNumber(t *testing.T) {
|
|||||||
t.Logf("orr %s, %s, %d", pattern.Destination, pattern.Source, pattern.Number)
|
t.Logf("orr %s, %s, %d", pattern.Destination, pattern.Source, pattern.Number)
|
||||||
code, encodable := arm.OrRegisterNumber(pattern.Destination, pattern.Source, pattern.Number)
|
code, encodable := arm.OrRegisterNumber(pattern.Destination, pattern.Source, pattern.Number)
|
||||||
assert.True(t, encodable)
|
assert.True(t, encodable)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +44,6 @@ func TestOrRegisterRegister(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("orr %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
t.Logf("orr %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
code := arm.OrRegisterRegister(pattern.Destination, pattern.Source, pattern.Operand)
|
code := arm.OrRegisterRegister(pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ func TestShiftLeftNumber(t *testing.T) {
|
|||||||
t.Logf("%b", pattern.Code)
|
t.Logf("%b", pattern.Code)
|
||||||
t.Logf("lsl %s, %s, %x", pattern.Destination, pattern.Source, pattern.Bits)
|
t.Logf("lsl %s, %s, %x", pattern.Destination, pattern.Source, pattern.Bits)
|
||||||
code := arm.ShiftLeftNumber(pattern.Destination, pattern.Source, pattern.Bits)
|
code := arm.ShiftLeftNumber(pattern.Destination, pattern.Source, pattern.Bits)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +47,6 @@ func TestShiftRightSignedNumber(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("asr %s, %s, %x", pattern.Destination, pattern.Source, pattern.Bits)
|
t.Logf("asr %s, %s, %x", pattern.Destination, pattern.Source, pattern.Bits)
|
||||||
code := arm.ShiftRightSignedNumber(pattern.Destination, pattern.Source, pattern.Bits)
|
code := arm.ShiftRightSignedNumber(pattern.Destination, pattern.Source, pattern.Bits)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,6 @@ func TestStorePair(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("stp %s, %s, [%s, #%d]!", pattern.Reg1, pattern.Reg2, pattern.Base, pattern.Offset)
|
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)
|
code := arm.StorePair(pattern.Reg1, pattern.Reg2, pattern.Base, pattern.Offset)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,6 @@ func TestStoreRegister(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("stur %s, [%s, #%d] %db", pattern.Source, pattern.Base, pattern.Offset, pattern.Length)
|
t.Logf("stur %s, [%s, #%d] %db", pattern.Source, pattern.Base, pattern.Offset, pattern.Length)
|
||||||
code := arm.StoreRegister(pattern.Source, pattern.Base, pattern.Offset, pattern.Length)
|
code := arm.StoreRegister(pattern.Source, pattern.Base, pattern.Offset, pattern.Length)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ func TestSubRegisterNumber(t *testing.T) {
|
|||||||
t.Logf("sub %s, %s, %d", pattern.Destination, pattern.Source, pattern.Number)
|
t.Logf("sub %s, %s, %d", pattern.Destination, pattern.Source, pattern.Number)
|
||||||
code, encodable := arm.SubRegisterNumber(pattern.Destination, pattern.Source, pattern.Number)
|
code, encodable := arm.SubRegisterNumber(pattern.Destination, pattern.Source, pattern.Number)
|
||||||
assert.True(t, encodable)
|
assert.True(t, encodable)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +41,6 @@ func TestSubRegisterRegister(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("sub %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
t.Logf("sub %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
code := arm.SubRegisterRegister(pattern.Destination, pattern.Source, pattern.Operand)
|
code := arm.SubRegisterRegister(pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ func TestXorRegisterNumber(t *testing.T) {
|
|||||||
t.Logf("eor %s, %s, %d", pattern.Destination, pattern.Source, pattern.Number)
|
t.Logf("eor %s, %s, %d", pattern.Destination, pattern.Source, pattern.Number)
|
||||||
code, encodable := arm.XorRegisterNumber(pattern.Destination, pattern.Source, pattern.Number)
|
code, encodable := arm.XorRegisterNumber(pattern.Destination, pattern.Source, pattern.Number)
|
||||||
assert.True(t, encodable)
|
assert.True(t, encodable)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +44,6 @@ func TestXorRegisterRegister(t *testing.T) {
|
|||||||
for _, pattern := range usagePatterns {
|
for _, pattern := range usagePatterns {
|
||||||
t.Logf("eor %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
t.Logf("eor %s, %s, %s", pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
code := arm.XorRegisterRegister(pattern.Destination, pattern.Source, pattern.Operand)
|
code := arm.XorRegisterRegister(pattern.Destination, pattern.Source, pattern.Operand)
|
||||||
assert.DeepEqual(t, code, pattern.Code)
|
assert.Equal(t, code, pattern.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,7 @@ import (
|
|||||||
"git.urbach.dev/go/assert"
|
"git.urbach.dev/go/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGeneral(t *testing.T) {
|
func TestConstants(t *testing.T) {
|
||||||
assert.DeepEqual(t, arm.Call(0), 0x94000000)
|
|
||||||
assert.DeepEqual(t, arm.Nop(), 0xD503201F)
|
assert.DeepEqual(t, arm.Nop(), 0xD503201F)
|
||||||
assert.DeepEqual(t, arm.Return(), 0xD65F03C0)
|
assert.DeepEqual(t, arm.Return(), 0xD65F03C0)
|
||||||
assert.DeepEqual(t, arm.Syscall(), 0xD4000001)
|
assert.DeepEqual(t, arm.Syscall(), 0xD4000001)
|
||||||
|
@ -24,7 +24,7 @@ func encodeLogicalImmediate(val uint) (N int, immr int, imms int, encodable bool
|
|||||||
return 0, 0, 0, false
|
return 0, 0, 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return N, immr, (imms & 0x3f), true
|
return N, immr, (imms & 0x3F), true
|
||||||
}
|
}
|
||||||
|
|
||||||
// clearTrailingOnes clears trailing one bits.
|
// clearTrailingOnes clears trailing one bits.
|
||||||
|
22
src/arm/condition.go
Normal file
22
src/arm/condition.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package arm
|
||||||
|
|
||||||
|
type condition uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
EQ condition = iota
|
||||||
|
NE
|
||||||
|
CS
|
||||||
|
CC
|
||||||
|
MI
|
||||||
|
PL
|
||||||
|
VS
|
||||||
|
VC
|
||||||
|
HI
|
||||||
|
LS
|
||||||
|
GE
|
||||||
|
LT
|
||||||
|
GT
|
||||||
|
LE
|
||||||
|
AL
|
||||||
|
NV
|
||||||
|
)
|
@ -4,14 +4,6 @@ import (
|
|||||||
"git.urbach.dev/cli/q/src/cpu"
|
"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.
|
// memory encodes an instruction with a register, a base register and an offset.
|
||||||
func memory(destination cpu.Register, base cpu.Register, imm9 int) uint32 {
|
func memory(destination cpu.Register, base cpu.Register, imm9 int) uint32 {
|
||||||
return uint32(imm9&mask9)<<12 | uint32(base)<<5 | uint32(destination)
|
return uint32(imm9&mask9)<<12 | uint32(base)<<5 | uint32(destination)
|
||||||
|
11
src/arm/mask.go
Normal file
11
src/arm/mask.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package arm
|
||||||
|
|
||||||
|
const (
|
||||||
|
mask6 = 0b111111
|
||||||
|
mask7 = 0b1111111
|
||||||
|
mask9 = 0b1_11111111
|
||||||
|
mask12 = 0b1111_11111111
|
||||||
|
mask16 = 0b11111111_11111111
|
||||||
|
mask19 = 0b111_11111111_11111111
|
||||||
|
mask26 = 0b11_11111111_11111111_11111111
|
||||||
|
)
|
@ -100,10 +100,12 @@ func (c *armCompiler) handleCallInstruction(instruction asm.Instruction) {
|
|||||||
|
|
||||||
pointer.Resolve = func() Address {
|
pointer.Resolve = func() Address {
|
||||||
destination, exists := c.codeLabels[label.Name]
|
destination, exists := c.codeLabels[label.Name]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
panic(fmt.Sprintf("unknown jump label %s", label.Name))
|
panic(fmt.Sprintf("unknown jump label %s", label.Name))
|
||||||
}
|
}
|
||||||
distance := (destination - position) / 4
|
|
||||||
|
distance := int(destination-position) / 4
|
||||||
return arm.Call(distance)
|
return arm.Call(distance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user