Added more tests
This commit is contained in:
@ -4,6 +4,5 @@ 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 &= 0b1111_1111_1111
|
||||
return 0b100100010<<23 | (uint32(number) << 10) | (uint32(source) << 5) | uint32(destination)
|
||||
return encodeRegisterNumberFlags(0b10, destination, source, number, false)
|
||||
}
|
||||
|
26
src/arm/Add_test.go
Normal file
26
src/arm/Add_test.go
Normal file
@ -0,0 +1,26 @@
|
||||
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 TestAddRegisterNumber(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Destination cpu.Register
|
||||
Source cpu.Register
|
||||
Number int
|
||||
Code uint32
|
||||
}{
|
||||
{arm.X0, arm.X0, 1, 0x91000400},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("add %s, %s, %d", pattern.Destination, pattern.Source, pattern.Number)
|
||||
code := arm.AddRegisterNumber(pattern.Destination, pattern.Source, pattern.Number)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
8
src/arm/Compare.go
Normal file
8
src/arm/Compare.go
Normal file
@ -0,0 +1,8 @@
|
||||
package arm
|
||||
|
||||
import "git.urbach.dev/cli/q/src/cpu"
|
||||
|
||||
// CompareRegisterNumber is an alias for a subtraction that updates the conditional flags and discards the result.
|
||||
func CompareRegisterNumber(register cpu.Register, number int) uint32 {
|
||||
return encodeRegisterNumberFlags(0b11, 0b11111, register, number, true)
|
||||
}
|
25
src/arm/Compare_test.go
Normal file
25
src/arm/Compare_test.go
Normal file
@ -0,0 +1,25 @@
|
||||
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 TestCompareRegisterNumber(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Source cpu.Register
|
||||
Number int
|
||||
Code uint32
|
||||
}{
|
||||
{arm.X0, 1, 0xF100041F},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("cmp %s, %d", pattern.Source, pattern.Number)
|
||||
code := arm.CompareRegisterNumber(pattern.Source, pattern.Number)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
@ -6,26 +6,6 @@ func Jump(offset int) uint32 {
|
||||
return 0b000101<<26 | uint32(offset)
|
||||
}
|
||||
|
||||
// JumpIfLess jumps if the result was less.
|
||||
func JumpIfLess(offset int) uint32 {
|
||||
return branchCond(0b1001, offset)
|
||||
}
|
||||
|
||||
// JumpIfLessOrEqual jumps if the result was less or equal.
|
||||
func JumpIfLessOrEqual(offset int) uint32 {
|
||||
return branchCond(0b1101, offset)
|
||||
}
|
||||
|
||||
// JumpIfGreater jumps if the result was greater.
|
||||
func JumpIfGreater(offset int) uint32 {
|
||||
return branchCond(0b1100, offset)
|
||||
}
|
||||
|
||||
// JumpIfGreaterOrEqual jumps if the result was greater or equal.
|
||||
func JumpIfGreaterOrEqual(offset int) uint32 {
|
||||
return branchCond(0b1010, offset)
|
||||
}
|
||||
|
||||
// JumpIfEqual jumps if the result was equal.
|
||||
func JumpIfEqual(offset int) uint32 {
|
||||
return branchCond(0b0000, offset)
|
||||
@ -36,6 +16,26 @@ func JumpIfNotEqual(offset int) uint32 {
|
||||
return branchCond(0b0001, offset)
|
||||
}
|
||||
|
||||
// JumpIfGreater jumps if the result was greater.
|
||||
func JumpIfGreater(offset int) uint32 {
|
||||
return branchCond(0b1100, offset)
|
||||
}
|
||||
|
||||
// JumpIfGreaterOrEqual jumps if the result was greater or equal.
|
||||
func JumpIfGreaterOrEqual(offset int) uint32 {
|
||||
return branchCond(0b1010, offset)
|
||||
}
|
||||
|
||||
// JumpIfLess jumps if the result was less.
|
||||
func JumpIfLess(offset int) uint32 {
|
||||
return branchCond(0b1001, offset)
|
||||
}
|
||||
|
||||
// JumpIfLessOrEqual jumps if the result was less or equal.
|
||||
func JumpIfLessOrEqual(offset int) uint32 {
|
||||
return branchCond(0b1101, offset)
|
||||
}
|
||||
|
||||
// branchCond performs a conditional branch to a PC-relative offset.
|
||||
func branchCond(cond uint32, offset int) uint32 {
|
||||
offset &= 0b111_1111_1111_1111_1111
|
||||
|
68
src/arm/Jump_test.go
Normal file
68
src/arm/Jump_test.go
Normal file
@ -0,0 +1,68 @@
|
||||
package arm_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.urbach.dev/cli/q/src/arm"
|
||||
"git.urbach.dev/go/assert"
|
||||
)
|
||||
|
||||
func TestJump(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Type byte
|
||||
Offset int
|
||||
Code uint32
|
||||
}{
|
||||
{0, 0, 0x14000000},
|
||||
{0, 1, 0x14000001},
|
||||
{0, -1, 0x17FFFFFF},
|
||||
|
||||
{1, 0, 0x54000000},
|
||||
{1, 1, 0x54000020},
|
||||
{1, -1, 0x54FFFFE0},
|
||||
|
||||
{2, 0, 0x54000001},
|
||||
{2, 1, 0x54000021},
|
||||
{2, -1, 0x54FFFFE1},
|
||||
|
||||
{3, 0, 0x5400000C},
|
||||
{3, 1, 0x5400002C},
|
||||
{3, -1, 0x54FFFFEC},
|
||||
|
||||
{4, 0, 0x5400000A},
|
||||
{4, 1, 0x5400002A},
|
||||
{4, -1, 0x54FFFFEA},
|
||||
|
||||
{5, 0, 0x54000009},
|
||||
{5, 1, 0x54000029},
|
||||
{5, -1, 0x54FFFFE9},
|
||||
|
||||
{6, 0, 0x5400000D},
|
||||
{6, 1, 0x5400002D},
|
||||
{6, -1, 0x54FFFFED},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("b %d", pattern.Offset)
|
||||
var code uint32
|
||||
|
||||
switch pattern.Type {
|
||||
case 0:
|
||||
code = arm.Jump(pattern.Offset)
|
||||
case 1:
|
||||
code = arm.JumpIfEqual(pattern.Offset)
|
||||
case 2:
|
||||
code = arm.JumpIfNotEqual(pattern.Offset)
|
||||
case 3:
|
||||
code = arm.JumpIfGreater(pattern.Offset)
|
||||
case 4:
|
||||
code = arm.JumpIfGreaterOrEqual(pattern.Offset)
|
||||
case 5:
|
||||
code = arm.JumpIfLess(pattern.Offset)
|
||||
case 6:
|
||||
code = arm.JumpIfLessOrEqual(pattern.Offset)
|
||||
}
|
||||
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
@ -4,6 +4,5 @@ import "git.urbach.dev/cli/q/src/cpu"
|
||||
|
||||
// SubRegisterNumber subtracts a number from the given register.
|
||||
func SubRegisterNumber(destination cpu.Register, source cpu.Register, number int) uint32 {
|
||||
number &= 0b1111_1111_1111
|
||||
return 0b111100010<<23 | (uint32(number) << 10) | (uint32(source) << 5) | uint32(destination)
|
||||
return encodeRegisterNumberFlags(0b11, destination, source, number, false)
|
||||
}
|
||||
|
26
src/arm/Sub_test.go
Normal file
26
src/arm/Sub_test.go
Normal file
@ -0,0 +1,26 @@
|
||||
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 TestSubRegisterNumber(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Destination cpu.Register
|
||||
Source cpu.Register
|
||||
Number int
|
||||
Code uint32
|
||||
}{
|
||||
{arm.X0, arm.X0, 1, 0xD1000400},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("sub %s, %s, %d", pattern.Destination, pattern.Source, pattern.Number)
|
||||
code := arm.SubRegisterNumber(pattern.Destination, pattern.Source, pattern.Number)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
16
src/arm/encode.go
Normal file
16
src/arm/encode.go
Normal file
@ -0,0 +1,16 @@
|
||||
package arm
|
||||
|
||||
import "git.urbach.dev/cli/q/src/cpu"
|
||||
|
||||
// encodeRegisterNumberFlags performs addition or subtraction on the given register
|
||||
// and optionally updates the condition flags based on the result.
|
||||
func encodeRegisterNumberFlags(op uint32, destination cpu.Register, source cpu.Register, number int, flags bool) uint32 {
|
||||
number &= 0b1111_1111_1111
|
||||
common := op<<30 | 0b100010<<23 | (uint32(number) << 10) | (uint32(source) << 5) | uint32(destination)
|
||||
|
||||
if flags {
|
||||
return 1<<29 | common
|
||||
}
|
||||
|
||||
return common
|
||||
}
|
@ -117,7 +117,7 @@ func (c *compiler) compileARM(x asm.Instruction) {
|
||||
switch x.Type {
|
||||
case asm.TypeRegisterNumber:
|
||||
operand := c.assembler.Param.RegisterNumber[x.Index]
|
||||
c.append(arm.SubRegisterNumber(0b11111, operand.Register, operand.Number))
|
||||
c.append(arm.CompareRegisterNumber(operand.Register, operand.Number))
|
||||
case asm.TypeRegisterRegister:
|
||||
panic("not implemented")
|
||||
}
|
||||
|
@ -8,13 +8,12 @@ import (
|
||||
)
|
||||
|
||||
func (c *compiler) jumpARM(x asm.Instruction) {
|
||||
label := c.assembler.Param.Label[x.Index]
|
||||
mnemonic := x.Mnemonic
|
||||
position := Address(len(c.code))
|
||||
label := c.assembler.Param.Label[x.Index]
|
||||
|
||||
pointer := &pointer{
|
||||
Position: position,
|
||||
OpSize: 0,
|
||||
Size: 4,
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,14 @@ func Jump8(code []byte, offset int8) []byte {
|
||||
return append(code, 0xEB, byte(offset))
|
||||
}
|
||||
|
||||
// JumpIfLess jumps if the result was less.
|
||||
func Jump8IfLess(code []byte, offset int8) []byte {
|
||||
return append(code, 0x7C, byte(offset))
|
||||
// JumpIfEqual jumps if the result was equal.
|
||||
func Jump8IfEqual(code []byte, offset int8) []byte {
|
||||
return append(code, 0x74, byte(offset))
|
||||
}
|
||||
|
||||
// JumpIfLessOrEqual jumps if the result was less or equal.
|
||||
func Jump8IfLessOrEqual(code []byte, offset int8) []byte {
|
||||
return append(code, 0x7E, byte(offset))
|
||||
// JumpIfNotEqual jumps if the result was not equal.
|
||||
func Jump8IfNotEqual(code []byte, offset int8) []byte {
|
||||
return append(code, 0x75, byte(offset))
|
||||
}
|
||||
|
||||
// JumpIfGreater jumps if the result was greater.
|
||||
@ -26,12 +26,12 @@ func Jump8IfGreaterOrEqual(code []byte, offset int8) []byte {
|
||||
return append(code, 0x7D, byte(offset))
|
||||
}
|
||||
|
||||
// JumpIfEqual jumps if the result was equal.
|
||||
func Jump8IfEqual(code []byte, offset int8) []byte {
|
||||
return append(code, 0x74, byte(offset))
|
||||
// JumpIfLess jumps if the result was less.
|
||||
func Jump8IfLess(code []byte, offset int8) []byte {
|
||||
return append(code, 0x7C, byte(offset))
|
||||
}
|
||||
|
||||
// JumpIfNotEqual jumps if the result was not equal.
|
||||
func Jump8IfNotEqual(code []byte, offset int8) []byte {
|
||||
return append(code, 0x75, byte(offset))
|
||||
// JumpIfLessOrEqual jumps if the result was less or equal.
|
||||
func Jump8IfLessOrEqual(code []byte, offset int8) []byte {
|
||||
return append(code, 0x7E, byte(offset))
|
||||
}
|
||||
|
Reference in New Issue
Block a user