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] Exclude unused functions
|
||||||
- [x] Constant folding
|
- [x] Constant folding
|
||||||
|
- [ ] Constant propagation
|
||||||
- [ ] Function call inlining
|
- [ ] Function call inlining
|
||||||
- [ ] Loop unrolls
|
- [ ] Loop unrolls
|
||||||
|
- [ ] Assembler optimization backend
|
||||||
|
|
||||||
### Linter
|
### Linter
|
||||||
|
|
||||||
|
@ -36,4 +36,4 @@ const (
|
|||||||
X30
|
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
|
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.
|
// AddRegisterNumber adds a number to the given register.
|
||||||
func AddRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
func AddRegisterNumber(code []byte, register cpu.Register, number int) []byte {
|
||||||
return encodeNum(code, AddressDirect, 0, destination, number, 0x83, 0x81)
|
return encodeNum(code, AddressDirect, 0, register, number, 0x83, 0x81)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddRegisterRegister adds a register value into another register.
|
// AddRegisterRegister adds a register value into another register.
|
||||||
func AddRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
func AddRegisterRegister(code []byte, register cpu.Register, operand cpu.Register) []byte {
|
||||||
return encode(code, AddressDirect, operand, destination, 8, 0x01)
|
return encode(code, AddressDirect, operand, register, 8, 0x01)
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AndRegisterNumber performs a bitwise AND using a register and a number.
|
// AndRegisterNumber performs a bitwise AND using a register and a number.
|
||||||
func AndRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
func AndRegisterNumber(code []byte, register cpu.Register, number int) []byte {
|
||||||
return encodeNum(code, AddressDirect, 0b100, destination, number, 0x83, 0x81)
|
return encodeNum(code, AddressDirect, 0b100, register, number, 0x83, 0x81)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AndRegisterRegister performs a bitwise AND using two registers.
|
// AndRegisterRegister performs a bitwise AND using two registers.
|
||||||
func AndRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
func AndRegisterRegister(code []byte, register cpu.Register, operand cpu.Register) []byte {
|
||||||
return encode(code, AddressDirect, operand, destination, 8, 0x21)
|
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"
|
import "git.akyoto.dev/cli/q/src/cpu"
|
||||||
|
|
||||||
// MulRegisterNumber multiplies a register with a number.
|
// MulRegisterNumber multiplies a register with a number.
|
||||||
func MulRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
func MulRegisterNumber(code []byte, register cpu.Register, number int) []byte {
|
||||||
return encodeNum(code, AddressDirect, destination, destination, number, 0x6B, 0x69)
|
return encodeNum(code, AddressDirect, register, register, number, 0x6B, 0x69)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MulRegisterRegister multiplies a register with another register.
|
// MulRegisterRegister multiplies a register with another register.
|
||||||
func MulRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
func MulRegisterRegister(code []byte, register cpu.Register, operand cpu.Register) []byte {
|
||||||
return encode(code, AddressDirect, destination, operand, 8, 0x0F, 0xAF)
|
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.
|
// OrRegisterNumber performs a bitwise OR using a register and a number.
|
||||||
func OrRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
func OrRegisterNumber(code []byte, register cpu.Register, number int) []byte {
|
||||||
return encodeNum(code, AddressDirect, 0b001, destination, number, 0x83, 0x81)
|
return encodeNum(code, AddressDirect, 0b001, register, number, 0x83, 0x81)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OrRegisterRegister performs a bitwise OR using two registers.
|
// OrRegisterRegister performs a bitwise OR using two registers.
|
||||||
func OrRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
func OrRegisterRegister(code []byte, register cpu.Register, operand cpu.Register) []byte {
|
||||||
return encode(code, AddressDirect, operand, destination, 8, 0x09)
|
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.
|
// SubRegisterNumber subtracts a number from the given register.
|
||||||
func SubRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
func SubRegisterNumber(code []byte, register cpu.Register, number int) []byte {
|
||||||
return encodeNum(code, AddressDirect, 0b101, destination, number, 0x83, 0x81)
|
return encodeNum(code, AddressDirect, 0b101, register, number, 0x83, 0x81)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubRegisterRegister subtracts a register value from another register.
|
// SubRegisterRegister subtracts a register value from another register.
|
||||||
func SubRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
func SubRegisterRegister(code []byte, register cpu.Register, operand cpu.Register) []byte {
|
||||||
return encode(code, AddressDirect, operand, destination, 8, 0x29)
|
return encode(code, AddressDirect, operand, register, 8, 0x29)
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// XorRegisterNumber performs a bitwise XOR using a register and a number.
|
// XorRegisterNumber performs a bitwise XOR using a register and a number.
|
||||||
func XorRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
func XorRegisterNumber(code []byte, register cpu.Register, number int) []byte {
|
||||||
return encodeNum(code, AddressDirect, 0b110, destination, number, 0x83, 0x81)
|
return encodeNum(code, AddressDirect, 0b110, register, number, 0x83, 0x81)
|
||||||
}
|
}
|
||||||
|
|
||||||
// XorRegisterRegister performs a bitwise XOR using two registers.
|
// XorRegisterRegister performs a bitwise XOR using two registers.
|
||||||
func XorRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
func XorRegisterRegister(code []byte, register cpu.Register, operand cpu.Register) []byte {
|
||||||
return encode(code, AddressDirect, operand, destination, 8, 0x31)
|
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