Added more tests
This commit is contained in:
parent
66569446b1
commit
d624a5f895
@ -67,8 +67,10 @@ Build a Linux x86-64 ELF executable from `examples/hello` and run it:
|
||||
|
||||
- [x] Exclude unused functions
|
||||
- [x] Constant folding
|
||||
- [ ] Constant propagation
|
||||
- [ ] Function call inlining
|
||||
- [ ] Loop unrolls
|
||||
- [ ] Assembler optimization backend
|
||||
|
||||
### Linter
|
||||
|
||||
|
@ -36,4 +36,4 @@ const (
|
||||
X30
|
||||
)
|
||||
|
||||
var SyscallArgs = []cpu.Register{X8, X0, X1, X2, X3, X4, X5}
|
||||
var SyscallInputRegisters = []cpu.Register{X8, X0, X1, X2, X3, X4, X5}
|
||||
|
12
src/arch/arm64/Registers_test.go
Normal file
12
src/arch/arm64/Registers_test.go
Normal file
@ -0,0 +1,12 @@
|
||||
package arm64_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/arch/arm64"
|
||||
"git.akyoto.dev/go/assert"
|
||||
)
|
||||
|
||||
func TestRegisters(t *testing.T) {
|
||||
assert.NotNil(t, arm64.SyscallInputRegisters)
|
||||
}
|
@ -37,4 +37,4 @@ const (
|
||||
X31
|
||||
)
|
||||
|
||||
var SyscallArgs = []cpu.Register{X10, X11, X12, X13, X14, X15, X16}
|
||||
var SyscallInputRegisters = []cpu.Register{X10, X11, X12, X13, X14, X15, X16}
|
||||
|
12
src/arch/riscv/Registers_test.go
Normal file
12
src/arch/riscv/Registers_test.go
Normal file
@ -0,0 +1,12 @@
|
||||
package riscv_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/arch/riscv"
|
||||
"git.akyoto.dev/go/assert"
|
||||
)
|
||||
|
||||
func TestRegisters(t *testing.T) {
|
||||
assert.NotNil(t, riscv.SyscallInputRegisters)
|
||||
}
|
@ -5,11 +5,11 @@ import (
|
||||
)
|
||||
|
||||
// AddRegisterNumber adds a number to the given register.
|
||||
func AddRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
||||
return encodeNum(code, AddressDirect, 0, destination, number, 0x83, 0x81)
|
||||
func AddRegisterNumber(code []byte, register cpu.Register, number int) []byte {
|
||||
return encodeNum(code, AddressDirect, 0, register, number, 0x83, 0x81)
|
||||
}
|
||||
|
||||
// AddRegisterRegister adds a register value into another register.
|
||||
func AddRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
||||
return encode(code, AddressDirect, operand, destination, 8, 0x01)
|
||||
func AddRegisterRegister(code []byte, register cpu.Register, operand cpu.Register) []byte {
|
||||
return encode(code, AddressDirect, operand, register, 8, 0x01)
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ import (
|
||||
)
|
||||
|
||||
// AndRegisterNumber performs a bitwise AND using a register and a number.
|
||||
func AndRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
||||
return encodeNum(code, AddressDirect, 0b100, destination, number, 0x83, 0x81)
|
||||
func AndRegisterNumber(code []byte, register cpu.Register, number int) []byte {
|
||||
return encodeNum(code, AddressDirect, 0b100, register, number, 0x83, 0x81)
|
||||
}
|
||||
|
||||
// AndRegisterRegister performs a bitwise AND using two registers.
|
||||
func AndRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
||||
return encode(code, AddressDirect, operand, destination, 8, 0x21)
|
||||
func AndRegisterRegister(code []byte, register cpu.Register, operand cpu.Register) []byte {
|
||||
return encode(code, AddressDirect, operand, register, 8, 0x21)
|
||||
}
|
||||
|
88
src/arch/x64/And_test.go
Normal file
88
src/arch/x64/And_test.go
Normal file
@ -0,0 +1,88 @@
|
||||
package x64_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/arch/x64"
|
||||
"git.akyoto.dev/cli/q/src/cpu"
|
||||
"git.akyoto.dev/go/assert"
|
||||
)
|
||||
|
||||
func TestAndRegisterNumber(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Register cpu.Register
|
||||
Number int
|
||||
Code []byte
|
||||
}{
|
||||
{x64.RAX, 1, []byte{0x48, 0x83, 0xE0, 0x01}},
|
||||
{x64.RCX, 1, []byte{0x48, 0x83, 0xE1, 0x01}},
|
||||
{x64.RDX, 1, []byte{0x48, 0x83, 0xE2, 0x01}},
|
||||
{x64.RBX, 1, []byte{0x48, 0x83, 0xE3, 0x01}},
|
||||
{x64.RSP, 1, []byte{0x48, 0x83, 0xE4, 0x01}},
|
||||
{x64.RBP, 1, []byte{0x48, 0x83, 0xE5, 0x01}},
|
||||
{x64.RSI, 1, []byte{0x48, 0x83, 0xE6, 0x01}},
|
||||
{x64.RDI, 1, []byte{0x48, 0x83, 0xE7, 0x01}},
|
||||
{x64.R8, 1, []byte{0x49, 0x83, 0xE0, 0x01}},
|
||||
{x64.R9, 1, []byte{0x49, 0x83, 0xE1, 0x01}},
|
||||
{x64.R10, 1, []byte{0x49, 0x83, 0xE2, 0x01}},
|
||||
{x64.R11, 1, []byte{0x49, 0x83, 0xE3, 0x01}},
|
||||
{x64.R12, 1, []byte{0x49, 0x83, 0xE4, 0x01}},
|
||||
{x64.R13, 1, []byte{0x49, 0x83, 0xE5, 0x01}},
|
||||
{x64.R14, 1, []byte{0x49, 0x83, 0xE6, 0x01}},
|
||||
{x64.R15, 1, []byte{0x49, 0x83, 0xE7, 0x01}},
|
||||
|
||||
{x64.RAX, 0x7FFFFFFF, []byte{0x48, 0x81, 0xE0, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RCX, 0x7FFFFFFF, []byte{0x48, 0x81, 0xE1, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RDX, 0x7FFFFFFF, []byte{0x48, 0x81, 0xE2, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RBX, 0x7FFFFFFF, []byte{0x48, 0x81, 0xE3, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RSP, 0x7FFFFFFF, []byte{0x48, 0x81, 0xE4, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RBP, 0x7FFFFFFF, []byte{0x48, 0x81, 0xE5, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RSI, 0x7FFFFFFF, []byte{0x48, 0x81, 0xE6, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RDI, 0x7FFFFFFF, []byte{0x48, 0x81, 0xE7, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R8, 0x7FFFFFFF, []byte{0x49, 0x81, 0xE0, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R9, 0x7FFFFFFF, []byte{0x49, 0x81, 0xE1, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R10, 0x7FFFFFFF, []byte{0x49, 0x81, 0xE2, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R11, 0x7FFFFFFF, []byte{0x49, 0x81, 0xE3, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R12, 0x7FFFFFFF, []byte{0x49, 0x81, 0xE4, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R13, 0x7FFFFFFF, []byte{0x49, 0x81, 0xE5, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R14, 0x7FFFFFFF, []byte{0x49, 0x81, 0xE6, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R15, 0x7FFFFFFF, []byte{0x49, 0x81, 0xE7, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("and %s, %x", pattern.Register, pattern.Number)
|
||||
code := x64.AndRegisterNumber(nil, pattern.Register, pattern.Number)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAndRegisterRegister(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Left cpu.Register
|
||||
Right cpu.Register
|
||||
Code []byte
|
||||
}{
|
||||
{x64.RAX, x64.R15, []byte{0x4C, 0x21, 0xF8}},
|
||||
{x64.RCX, x64.R14, []byte{0x4C, 0x21, 0xF1}},
|
||||
{x64.RDX, x64.R13, []byte{0x4C, 0x21, 0xEA}},
|
||||
{x64.RBX, x64.R12, []byte{0x4C, 0x21, 0xE3}},
|
||||
{x64.RSP, x64.R11, []byte{0x4C, 0x21, 0xDC}},
|
||||
{x64.RBP, x64.R10, []byte{0x4C, 0x21, 0xD5}},
|
||||
{x64.RSI, x64.R9, []byte{0x4C, 0x21, 0xCE}},
|
||||
{x64.RDI, x64.R8, []byte{0x4C, 0x21, 0xC7}},
|
||||
{x64.R8, x64.RDI, []byte{0x49, 0x21, 0xF8}},
|
||||
{x64.R9, x64.RSI, []byte{0x49, 0x21, 0xF1}},
|
||||
{x64.R10, x64.RBP, []byte{0x49, 0x21, 0xEA}},
|
||||
{x64.R11, x64.RSP, []byte{0x49, 0x21, 0xE3}},
|
||||
{x64.R12, x64.RBX, []byte{0x49, 0x21, 0xDC}},
|
||||
{x64.R13, x64.RDX, []byte{0x49, 0x21, 0xD5}},
|
||||
{x64.R14, x64.RCX, []byte{0x49, 0x21, 0xCE}},
|
||||
{x64.R15, x64.RAX, []byte{0x49, 0x21, 0xC7}},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("and %s, %s", pattern.Left, pattern.Right)
|
||||
code := x64.AndRegisterRegister(nil, pattern.Left, pattern.Right)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
@ -3,11 +3,11 @@ package x64
|
||||
import "git.akyoto.dev/cli/q/src/cpu"
|
||||
|
||||
// MulRegisterNumber multiplies a register with a number.
|
||||
func MulRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
||||
return encodeNum(code, AddressDirect, destination, destination, number, 0x6B, 0x69)
|
||||
func MulRegisterNumber(code []byte, register cpu.Register, number int) []byte {
|
||||
return encodeNum(code, AddressDirect, register, register, number, 0x6B, 0x69)
|
||||
}
|
||||
|
||||
// MulRegisterRegister multiplies a register with another register.
|
||||
func MulRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
||||
return encode(code, AddressDirect, destination, operand, 8, 0x0F, 0xAF)
|
||||
func MulRegisterRegister(code []byte, register cpu.Register, operand cpu.Register) []byte {
|
||||
return encode(code, AddressDirect, register, operand, 8, 0x0F, 0xAF)
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ import (
|
||||
)
|
||||
|
||||
// OrRegisterNumber performs a bitwise OR using a register and a number.
|
||||
func OrRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
||||
return encodeNum(code, AddressDirect, 0b001, destination, number, 0x83, 0x81)
|
||||
func OrRegisterNumber(code []byte, register cpu.Register, number int) []byte {
|
||||
return encodeNum(code, AddressDirect, 0b001, register, number, 0x83, 0x81)
|
||||
}
|
||||
|
||||
// OrRegisterRegister performs a bitwise OR using two registers.
|
||||
func OrRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
||||
return encode(code, AddressDirect, operand, destination, 8, 0x09)
|
||||
func OrRegisterRegister(code []byte, register cpu.Register, operand cpu.Register) []byte {
|
||||
return encode(code, AddressDirect, operand, register, 8, 0x09)
|
||||
}
|
||||
|
88
src/arch/x64/Or_test.go
Normal file
88
src/arch/x64/Or_test.go
Normal file
@ -0,0 +1,88 @@
|
||||
package x64_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/arch/x64"
|
||||
"git.akyoto.dev/cli/q/src/cpu"
|
||||
"git.akyoto.dev/go/assert"
|
||||
)
|
||||
|
||||
func TestOrRegisterNumber(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Register cpu.Register
|
||||
Number int
|
||||
Code []byte
|
||||
}{
|
||||
{x64.RAX, 1, []byte{0x48, 0x83, 0xC8, 0x01}},
|
||||
{x64.RCX, 1, []byte{0x48, 0x83, 0xC9, 0x01}},
|
||||
{x64.RDX, 1, []byte{0x48, 0x83, 0xCA, 0x01}},
|
||||
{x64.RBX, 1, []byte{0x48, 0x83, 0xCB, 0x01}},
|
||||
{x64.RSP, 1, []byte{0x48, 0x83, 0xCC, 0x01}},
|
||||
{x64.RBP, 1, []byte{0x48, 0x83, 0xCD, 0x01}},
|
||||
{x64.RSI, 1, []byte{0x48, 0x83, 0xCE, 0x01}},
|
||||
{x64.RDI, 1, []byte{0x48, 0x83, 0xCF, 0x01}},
|
||||
{x64.R8, 1, []byte{0x49, 0x83, 0xC8, 0x01}},
|
||||
{x64.R9, 1, []byte{0x49, 0x83, 0xC9, 0x01}},
|
||||
{x64.R10, 1, []byte{0x49, 0x83, 0xCA, 0x01}},
|
||||
{x64.R11, 1, []byte{0x49, 0x83, 0xCB, 0x01}},
|
||||
{x64.R12, 1, []byte{0x49, 0x83, 0xCC, 0x01}},
|
||||
{x64.R13, 1, []byte{0x49, 0x83, 0xCD, 0x01}},
|
||||
{x64.R14, 1, []byte{0x49, 0x83, 0xCE, 0x01}},
|
||||
{x64.R15, 1, []byte{0x49, 0x83, 0xCF, 0x01}},
|
||||
|
||||
{x64.RAX, 0x7FFFFFFF, []byte{0x48, 0x81, 0xC8, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RCX, 0x7FFFFFFF, []byte{0x48, 0x81, 0xC9, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RDX, 0x7FFFFFFF, []byte{0x48, 0x81, 0xCA, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RBX, 0x7FFFFFFF, []byte{0x48, 0x81, 0xCB, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RSP, 0x7FFFFFFF, []byte{0x48, 0x81, 0xCC, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RBP, 0x7FFFFFFF, []byte{0x48, 0x81, 0xCD, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RSI, 0x7FFFFFFF, []byte{0x48, 0x81, 0xCE, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RDI, 0x7FFFFFFF, []byte{0x48, 0x81, 0xCF, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R8, 0x7FFFFFFF, []byte{0x49, 0x81, 0xC8, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R9, 0x7FFFFFFF, []byte{0x49, 0x81, 0xC9, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R10, 0x7FFFFFFF, []byte{0x49, 0x81, 0xCA, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R11, 0x7FFFFFFF, []byte{0x49, 0x81, 0xCB, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R12, 0x7FFFFFFF, []byte{0x49, 0x81, 0xCC, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R13, 0x7FFFFFFF, []byte{0x49, 0x81, 0xCD, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R14, 0x7FFFFFFF, []byte{0x49, 0x81, 0xCE, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R15, 0x7FFFFFFF, []byte{0x49, 0x81, 0xCF, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("or %s, %x", pattern.Register, pattern.Number)
|
||||
code := x64.OrRegisterNumber(nil, pattern.Register, pattern.Number)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrRegisterRegister(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Left cpu.Register
|
||||
Right cpu.Register
|
||||
Code []byte
|
||||
}{
|
||||
{x64.RAX, x64.R15, []byte{0x4C, 0x09, 0xF8}},
|
||||
{x64.RCX, x64.R14, []byte{0x4C, 0x09, 0xF1}},
|
||||
{x64.RDX, x64.R13, []byte{0x4C, 0x09, 0xEA}},
|
||||
{x64.RBX, x64.R12, []byte{0x4C, 0x09, 0xE3}},
|
||||
{x64.RSP, x64.R11, []byte{0x4C, 0x09, 0xDC}},
|
||||
{x64.RBP, x64.R10, []byte{0x4C, 0x09, 0xD5}},
|
||||
{x64.RSI, x64.R9, []byte{0x4C, 0x09, 0xCE}},
|
||||
{x64.RDI, x64.R8, []byte{0x4C, 0x09, 0xC7}},
|
||||
{x64.R8, x64.RDI, []byte{0x49, 0x09, 0xF8}},
|
||||
{x64.R9, x64.RSI, []byte{0x49, 0x09, 0xF1}},
|
||||
{x64.R10, x64.RBP, []byte{0x49, 0x09, 0xEA}},
|
||||
{x64.R11, x64.RSP, []byte{0x49, 0x09, 0xE3}},
|
||||
{x64.R12, x64.RBX, []byte{0x49, 0x09, 0xDC}},
|
||||
{x64.R13, x64.RDX, []byte{0x49, 0x09, 0xD5}},
|
||||
{x64.R14, x64.RCX, []byte{0x49, 0x09, 0xCE}},
|
||||
{x64.R15, x64.RAX, []byte{0x49, 0x09, 0xC7}},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("or %s, %s", pattern.Left, pattern.Right)
|
||||
code := x64.OrRegisterRegister(nil, pattern.Left, pattern.Right)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
12
src/arch/x64/Registers_test.go
Normal file
12
src/arch/x64/Registers_test.go
Normal file
@ -0,0 +1,12 @@
|
||||
package x64_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/arch/x64"
|
||||
"git.akyoto.dev/go/assert"
|
||||
)
|
||||
|
||||
func TestRegisters(t *testing.T) {
|
||||
assert.NotContains(t, x64.GeneralRegisters, x64.RSP)
|
||||
}
|
71
src/arch/x64/Shift_test.go
Normal file
71
src/arch/x64/Shift_test.go
Normal file
@ -0,0 +1,71 @@
|
||||
package x64_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/arch/x64"
|
||||
"git.akyoto.dev/cli/q/src/cpu"
|
||||
"git.akyoto.dev/go/assert"
|
||||
)
|
||||
|
||||
func TestShiftLeftNumber(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Register cpu.Register
|
||||
Number int
|
||||
Code []byte
|
||||
}{
|
||||
{x64.RAX, 1, []byte{0x48, 0xC1, 0xE0, 0x01}},
|
||||
{x64.RCX, 1, []byte{0x48, 0xC1, 0xE1, 0x01}},
|
||||
{x64.RDX, 1, []byte{0x48, 0xC1, 0xE2, 0x01}},
|
||||
{x64.RBX, 1, []byte{0x48, 0xC1, 0xE3, 0x01}},
|
||||
{x64.RSP, 1, []byte{0x48, 0xC1, 0xE4, 0x01}},
|
||||
{x64.RBP, 1, []byte{0x48, 0xC1, 0xE5, 0x01}},
|
||||
{x64.RSI, 1, []byte{0x48, 0xC1, 0xE6, 0x01}},
|
||||
{x64.RDI, 1, []byte{0x48, 0xC1, 0xE7, 0x01}},
|
||||
{x64.R8, 1, []byte{0x49, 0xC1, 0xE0, 0x01}},
|
||||
{x64.R9, 1, []byte{0x49, 0xC1, 0xE1, 0x01}},
|
||||
{x64.R10, 1, []byte{0x49, 0xC1, 0xE2, 0x01}},
|
||||
{x64.R11, 1, []byte{0x49, 0xC1, 0xE3, 0x01}},
|
||||
{x64.R12, 1, []byte{0x49, 0xC1, 0xE4, 0x01}},
|
||||
{x64.R13, 1, []byte{0x49, 0xC1, 0xE5, 0x01}},
|
||||
{x64.R14, 1, []byte{0x49, 0xC1, 0xE6, 0x01}},
|
||||
{x64.R15, 1, []byte{0x49, 0xC1, 0xE7, 0x01}},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("shl %s, %x", pattern.Register, pattern.Number)
|
||||
code := x64.ShiftLeftNumber(nil, pattern.Register, byte(pattern.Number))
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShiftRightSignedNumber(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Register cpu.Register
|
||||
Number int
|
||||
Code []byte
|
||||
}{
|
||||
{x64.RAX, 1, []byte{0x48, 0xC1, 0xF8, 0x01}},
|
||||
{x64.RCX, 1, []byte{0x48, 0xC1, 0xF9, 0x01}},
|
||||
{x64.RDX, 1, []byte{0x48, 0xC1, 0xFA, 0x01}},
|
||||
{x64.RBX, 1, []byte{0x48, 0xC1, 0xFB, 0x01}},
|
||||
{x64.RSP, 1, []byte{0x48, 0xC1, 0xFC, 0x01}},
|
||||
{x64.RBP, 1, []byte{0x48, 0xC1, 0xFD, 0x01}},
|
||||
{x64.RSI, 1, []byte{0x48, 0xC1, 0xFE, 0x01}},
|
||||
{x64.RDI, 1, []byte{0x48, 0xC1, 0xFF, 0x01}},
|
||||
{x64.R8, 1, []byte{0x49, 0xC1, 0xF8, 0x01}},
|
||||
{x64.R9, 1, []byte{0x49, 0xC1, 0xF9, 0x01}},
|
||||
{x64.R10, 1, []byte{0x49, 0xC1, 0xFA, 0x01}},
|
||||
{x64.R11, 1, []byte{0x49, 0xC1, 0xFB, 0x01}},
|
||||
{x64.R12, 1, []byte{0x49, 0xC1, 0xFC, 0x01}},
|
||||
{x64.R13, 1, []byte{0x49, 0xC1, 0xFD, 0x01}},
|
||||
{x64.R14, 1, []byte{0x49, 0xC1, 0xFE, 0x01}},
|
||||
{x64.R15, 1, []byte{0x49, 0xC1, 0xFF, 0x01}},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("sar %s, %x", pattern.Register, pattern.Number)
|
||||
code := x64.ShiftRightSignedNumber(nil, pattern.Register, byte(pattern.Number))
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
@ -5,11 +5,11 @@ import (
|
||||
)
|
||||
|
||||
// SubRegisterNumber subtracts a number from the given register.
|
||||
func SubRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
||||
return encodeNum(code, AddressDirect, 0b101, destination, number, 0x83, 0x81)
|
||||
func SubRegisterNumber(code []byte, register cpu.Register, number int) []byte {
|
||||
return encodeNum(code, AddressDirect, 0b101, register, number, 0x83, 0x81)
|
||||
}
|
||||
|
||||
// SubRegisterRegister subtracts a register value from another register.
|
||||
func SubRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
||||
return encode(code, AddressDirect, operand, destination, 8, 0x29)
|
||||
func SubRegisterRegister(code []byte, register cpu.Register, operand cpu.Register) []byte {
|
||||
return encode(code, AddressDirect, operand, register, 8, 0x29)
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ import (
|
||||
)
|
||||
|
||||
// XorRegisterNumber performs a bitwise XOR using a register and a number.
|
||||
func XorRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
||||
return encodeNum(code, AddressDirect, 0b110, destination, number, 0x83, 0x81)
|
||||
func XorRegisterNumber(code []byte, register cpu.Register, number int) []byte {
|
||||
return encodeNum(code, AddressDirect, 0b110, register, number, 0x83, 0x81)
|
||||
}
|
||||
|
||||
// XorRegisterRegister performs a bitwise XOR using two registers.
|
||||
func XorRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
||||
return encode(code, AddressDirect, operand, destination, 8, 0x31)
|
||||
func XorRegisterRegister(code []byte, register cpu.Register, operand cpu.Register) []byte {
|
||||
return encode(code, AddressDirect, operand, register, 8, 0x31)
|
||||
}
|
||||
|
88
src/arch/x64/Xor_test.go
Normal file
88
src/arch/x64/Xor_test.go
Normal file
@ -0,0 +1,88 @@
|
||||
package x64_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.akyoto.dev/cli/q/src/arch/x64"
|
||||
"git.akyoto.dev/cli/q/src/cpu"
|
||||
"git.akyoto.dev/go/assert"
|
||||
)
|
||||
|
||||
func TestXorRegisterNumber(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Register cpu.Register
|
||||
Number int
|
||||
Code []byte
|
||||
}{
|
||||
{x64.RAX, 1, []byte{0x48, 0x83, 0xF0, 0x01}},
|
||||
{x64.RCX, 1, []byte{0x48, 0x83, 0xF1, 0x01}},
|
||||
{x64.RDX, 1, []byte{0x48, 0x83, 0xF2, 0x01}},
|
||||
{x64.RBX, 1, []byte{0x48, 0x83, 0xF3, 0x01}},
|
||||
{x64.RSP, 1, []byte{0x48, 0x83, 0xF4, 0x01}},
|
||||
{x64.RBP, 1, []byte{0x48, 0x83, 0xF5, 0x01}},
|
||||
{x64.RSI, 1, []byte{0x48, 0x83, 0xF6, 0x01}},
|
||||
{x64.RDI, 1, []byte{0x48, 0x83, 0xF7, 0x01}},
|
||||
{x64.R8, 1, []byte{0x49, 0x83, 0xF0, 0x01}},
|
||||
{x64.R9, 1, []byte{0x49, 0x83, 0xF1, 0x01}},
|
||||
{x64.R10, 1, []byte{0x49, 0x83, 0xF2, 0x01}},
|
||||
{x64.R11, 1, []byte{0x49, 0x83, 0xF3, 0x01}},
|
||||
{x64.R12, 1, []byte{0x49, 0x83, 0xF4, 0x01}},
|
||||
{x64.R13, 1, []byte{0x49, 0x83, 0xF5, 0x01}},
|
||||
{x64.R14, 1, []byte{0x49, 0x83, 0xF6, 0x01}},
|
||||
{x64.R15, 1, []byte{0x49, 0x83, 0xF7, 0x01}},
|
||||
|
||||
{x64.RAX, 0x7FFFFFFF, []byte{0x48, 0x81, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RCX, 0x7FFFFFFF, []byte{0x48, 0x81, 0xF1, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RDX, 0x7FFFFFFF, []byte{0x48, 0x81, 0xF2, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RBX, 0x7FFFFFFF, []byte{0x48, 0x81, 0xF3, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RSP, 0x7FFFFFFF, []byte{0x48, 0x81, 0xF4, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RBP, 0x7FFFFFFF, []byte{0x48, 0x81, 0xF5, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RSI, 0x7FFFFFFF, []byte{0x48, 0x81, 0xF6, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.RDI, 0x7FFFFFFF, []byte{0x48, 0x81, 0xF7, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R8, 0x7FFFFFFF, []byte{0x49, 0x81, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R9, 0x7FFFFFFF, []byte{0x49, 0x81, 0xF1, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R10, 0x7FFFFFFF, []byte{0x49, 0x81, 0xF2, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R11, 0x7FFFFFFF, []byte{0x49, 0x81, 0xF3, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R12, 0x7FFFFFFF, []byte{0x49, 0x81, 0xF4, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R13, 0x7FFFFFFF, []byte{0x49, 0x81, 0xF5, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R14, 0x7FFFFFFF, []byte{0x49, 0x81, 0xF6, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
{x64.R15, 0x7FFFFFFF, []byte{0x49, 0x81, 0xF7, 0xFF, 0xFF, 0xFF, 0x7F}},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("xor %s, %x", pattern.Register, pattern.Number)
|
||||
code := x64.XorRegisterNumber(nil, pattern.Register, pattern.Number)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestXorRegisterRegister(t *testing.T) {
|
||||
usagePatterns := []struct {
|
||||
Left cpu.Register
|
||||
Right cpu.Register
|
||||
Code []byte
|
||||
}{
|
||||
{x64.RAX, x64.R15, []byte{0x4C, 0x31, 0xF8}},
|
||||
{x64.RCX, x64.R14, []byte{0x4C, 0x31, 0xF1}},
|
||||
{x64.RDX, x64.R13, []byte{0x4C, 0x31, 0xEA}},
|
||||
{x64.RBX, x64.R12, []byte{0x4C, 0x31, 0xE3}},
|
||||
{x64.RSP, x64.R11, []byte{0x4C, 0x31, 0xDC}},
|
||||
{x64.RBP, x64.R10, []byte{0x4C, 0x31, 0xD5}},
|
||||
{x64.RSI, x64.R9, []byte{0x4C, 0x31, 0xCE}},
|
||||
{x64.RDI, x64.R8, []byte{0x4C, 0x31, 0xC7}},
|
||||
{x64.R8, x64.RDI, []byte{0x49, 0x31, 0xF8}},
|
||||
{x64.R9, x64.RSI, []byte{0x49, 0x31, 0xF1}},
|
||||
{x64.R10, x64.RBP, []byte{0x49, 0x31, 0xEA}},
|
||||
{x64.R11, x64.RSP, []byte{0x49, 0x31, 0xE3}},
|
||||
{x64.R12, x64.RBX, []byte{0x49, 0x31, 0xDC}},
|
||||
{x64.R13, x64.RDX, []byte{0x49, 0x31, 0xD5}},
|
||||
{x64.R14, x64.RCX, []byte{0x49, 0x31, 0xCE}},
|
||||
{x64.R15, x64.RAX, []byte{0x49, 0x31, 0xC7}},
|
||||
}
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("xor %s, %s", pattern.Left, pattern.Right)
|
||||
code := x64.XorRegisterRegister(nil, pattern.Left, pattern.Right)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user