Improved function names
This commit is contained in:
parent
e6462266ef
commit
e69d695f6b
@ -4,39 +4,12 @@ import (
|
||||
"git.akyoto.dev/cli/q/src/build/cpu"
|
||||
)
|
||||
|
||||
// AddRegNum adds a number to the given register.
|
||||
func AddRegNum(code []byte, destination cpu.Register, number int) []byte {
|
||||
return numRegReg(code, 0, byte(destination), number, 0x83, 0x81)
|
||||
// AddRegisterNumber adds a number to the given register.
|
||||
func AddRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
||||
return regRegNum(code, 0, byte(destination), number, 0x83, 0x81)
|
||||
}
|
||||
|
||||
// AddRegReg adds a number to the given register.
|
||||
func AddRegReg(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
||||
// AddRegisterRegister adds a register value into another register.
|
||||
func AddRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
||||
return regReg(code, byte(operand), byte(destination), 0x01)
|
||||
}
|
||||
|
||||
func regReg(code []byte, reg byte, rm byte, opCodes ...byte) []byte {
|
||||
w := byte(1) // Indicates a 64-bit register.
|
||||
r := byte(0) // Extension to the "reg" field in ModRM.
|
||||
x := byte(0) // Extension to the SIB index field.
|
||||
b := byte(0) // Extension to the "rm" field in ModRM or the SIB base (r8 up to r15 use this).
|
||||
mod := byte(0b11) // Direct addressing mode, no register offsets.
|
||||
|
||||
if reg > 0b111 {
|
||||
r = 1
|
||||
reg &= 0b111
|
||||
}
|
||||
|
||||
if rm > 0b111 {
|
||||
b = 1
|
||||
rm &= 0b111
|
||||
}
|
||||
|
||||
rex := REX(w, r, x, b)
|
||||
modRM := ModRM(mod, reg, rm)
|
||||
|
||||
code = append(code, rex)
|
||||
code = append(code, opCodes...)
|
||||
code = append(code, modRM)
|
||||
|
||||
return code
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ func TestAddRegisterNumber(t *testing.T) {
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("add %s, %x", pattern.Register, pattern.Number)
|
||||
code := x64.AddRegNum(nil, pattern.Register, pattern.Number)
|
||||
code := x64.AddRegisterNumber(nil, pattern.Register, pattern.Number)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
||||
@ -82,7 +82,7 @@ func TestAddRegisterRegister(t *testing.T) {
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("add %s, %s", pattern.Left, pattern.Right)
|
||||
code := x64.AddRegReg(nil, pattern.Left, pattern.Right)
|
||||
code := x64.AddRegisterRegister(nil, pattern.Left, pattern.Right)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package x64
|
||||
|
||||
import "git.akyoto.dev/cli/q/src/build/cpu"
|
||||
|
||||
// DivReg divides RDX:RAX by the value in the register.
|
||||
func DivReg(code []byte, divisor cpu.Register) []byte {
|
||||
// DivRegister divides RDX:RAX by the value in the register.
|
||||
func DivRegister(code []byte, divisor cpu.Register) []byte {
|
||||
rex := byte(0x48)
|
||||
|
||||
if divisor >= 8 {
|
||||
|
@ -33,7 +33,7 @@ func TestDivRegister(t *testing.T) {
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("idiv %s", pattern.Register)
|
||||
code := x64.DivReg(nil, pattern.Register)
|
||||
code := x64.DivRegister(nil, pattern.Register)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package x64
|
||||
|
||||
import "git.akyoto.dev/cli/q/src/build/cpu"
|
||||
|
||||
// MoveRegNum32 moves a 32 bit integer into the given register.
|
||||
func MoveRegNum32(code []byte, destination cpu.Register, number uint32) []byte {
|
||||
// MoveRegisterNumber32 moves a 32 bit integer into the given register.
|
||||
func MoveRegisterNumber32(code []byte, destination cpu.Register, number uint32) []byte {
|
||||
if destination >= 8 {
|
||||
code = append(code, REX(0, 0, 0, 1))
|
||||
destination -= 8
|
||||
@ -19,8 +19,8 @@ func MoveRegNum32(code []byte, destination cpu.Register, number uint32) []byte {
|
||||
)
|
||||
}
|
||||
|
||||
// MoveRegReg64 moves a register value into another register.
|
||||
func MoveRegReg64(code []byte, destination cpu.Register, source cpu.Register) []byte {
|
||||
// MoveRegisterRegister64 moves a register value into another register.
|
||||
func MoveRegisterRegister64(code []byte, destination cpu.Register, source cpu.Register) []byte {
|
||||
r := byte(0) // Extension to the "reg" field in ModRM.
|
||||
b := byte(0) // Extension to the "rm" field in ModRM or the SIB base (r8 up to r15 use this).
|
||||
|
||||
|
@ -2,12 +2,12 @@ package x64
|
||||
|
||||
import "git.akyoto.dev/cli/q/src/build/cpu"
|
||||
|
||||
// MulRegNum multiplies a register with a number.
|
||||
func MulRegNum(code []byte, destination cpu.Register, number int) []byte {
|
||||
return numRegReg(code, byte(destination), byte(destination), number, 0x6B, 0x69)
|
||||
// MulRegisterNumber multiplies a register with a number.
|
||||
func MulRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
||||
return regRegNum(code, byte(destination), byte(destination), number, 0x6B, 0x69)
|
||||
}
|
||||
|
||||
// MulRegReg multiplies a register with another register.
|
||||
func MulRegReg(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
||||
// MulRegisterRegister multiplies a register with another register.
|
||||
func MulRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
||||
return regReg(code, byte(destination), byte(operand), 0x0F, 0xAF)
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ func TestMulRegisterNumber(t *testing.T) {
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("mul %s, %x", pattern.Register, pattern.Number)
|
||||
code := x64.MulRegNum(nil, pattern.Register, pattern.Number)
|
||||
code := x64.MulRegisterNumber(nil, pattern.Register, pattern.Number)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
||||
@ -82,7 +82,7 @@ func TestMulRegisterRegister(t *testing.T) {
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("mul %s, %s", pattern.Left, pattern.Right)
|
||||
code := x64.MulRegReg(nil, pattern.Left, pattern.Right)
|
||||
code := x64.MulRegisterRegister(nil, pattern.Left, pattern.Right)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package x64
|
||||
|
||||
import "git.akyoto.dev/cli/q/src/build/cpu"
|
||||
|
||||
// PopReg pops a value from the stack and saves it into the register.
|
||||
func PopReg(code []byte, register cpu.Register) []byte {
|
||||
// PopRegister pops a value from the stack and saves it into the register.
|
||||
func PopRegister(code []byte, register cpu.Register) []byte {
|
||||
if register >= 8 {
|
||||
code = append(code, REX(0, 0, 0, 1))
|
||||
register -= 8
|
||||
|
@ -33,7 +33,7 @@ func TestPopRegister(t *testing.T) {
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("pop %s", pattern.Register)
|
||||
code := x64.PopReg(nil, pattern.Register)
|
||||
code := x64.PopRegister(nil, pattern.Register)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package x64
|
||||
|
||||
import "git.akyoto.dev/cli/q/src/build/cpu"
|
||||
|
||||
// PushReg pushes the value inside the register onto the stack.
|
||||
func PushReg(code []byte, register cpu.Register) []byte {
|
||||
// PushRegister pushes the value inside the register onto the stack.
|
||||
func PushRegister(code []byte, register cpu.Register) []byte {
|
||||
if register >= 8 {
|
||||
code = append(code, REX(0, 0, 0, 1))
|
||||
register -= 8
|
||||
|
@ -33,7 +33,7 @@ func TestPushRegister(t *testing.T) {
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("push %s", pattern.Register)
|
||||
code := x64.PushReg(nil, pattern.Register)
|
||||
code := x64.PushRegister(nil, pattern.Register)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,12 @@ import (
|
||||
"git.akyoto.dev/cli/q/src/build/cpu"
|
||||
)
|
||||
|
||||
// SubRegNum subtracts a number from the given register.
|
||||
func SubRegNum(code []byte, destination cpu.Register, number int) []byte {
|
||||
return numRegReg(code, 0b101, byte(destination), number, 0x83, 0x81)
|
||||
// SubRegisterNumber subtracts a number from the given register.
|
||||
func SubRegisterNumber(code []byte, destination cpu.Register, number int) []byte {
|
||||
return regRegNum(code, 0b101, byte(destination), number, 0x83, 0x81)
|
||||
}
|
||||
|
||||
// SubRegReg subtracts a register value from another register.
|
||||
func SubRegReg(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
||||
// SubRegisterRegister subtracts a register value from another register.
|
||||
func SubRegisterRegister(code []byte, destination cpu.Register, operand cpu.Register) []byte {
|
||||
return regReg(code, byte(operand), byte(destination), 0x29)
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ func TestSubRegisterNumber(t *testing.T) {
|
||||
|
||||
for _, pattern := range usagePatterns {
|
||||
t.Logf("sub %s, %x", pattern.Register, pattern.Number)
|
||||
code := x64.SubRegNum(nil, pattern.Register, pattern.Number)
|
||||
code := x64.SubRegisterNumber(nil, pattern.Register, pattern.Number)
|
||||
assert.DeepEqual(t, code, pattern.Code)
|
||||
}
|
||||
}
|
||||
|
@ -2,5 +2,5 @@ package x64
|
||||
|
||||
// Syscall is the primary way to communicate with the OS kernel.
|
||||
func Syscall(code []byte) []byte {
|
||||
return append(code, 0x0f, 0x05)
|
||||
return append(code, 0x0F, 0x05)
|
||||
}
|
||||
|
29
src/build/arch/x64/regReg.go
Normal file
29
src/build/arch/x64/regReg.go
Normal file
@ -0,0 +1,29 @@
|
||||
package x64
|
||||
|
||||
// regReg encodes an operation using 2 registers.
|
||||
func regReg(code []byte, reg byte, rm byte, opCodes ...byte) []byte {
|
||||
w := byte(1) // Indicates a 64-bit register.
|
||||
r := byte(0) // Extension to the "reg" field in ModRM.
|
||||
x := byte(0) // Extension to the SIB index field.
|
||||
b := byte(0) // Extension to the "rm" field in ModRM or the SIB base (r8 up to r15 use this).
|
||||
mod := byte(0b11) // Direct addressing mode, no register offsets.
|
||||
|
||||
if reg > 0b111 {
|
||||
r = 1
|
||||
reg &= 0b111
|
||||
}
|
||||
|
||||
if rm > 0b111 {
|
||||
b = 1
|
||||
rm &= 0b111
|
||||
}
|
||||
|
||||
rex := REX(w, r, x, b)
|
||||
modRM := ModRM(mod, reg, rm)
|
||||
|
||||
code = append(code, rex)
|
||||
code = append(code, opCodes...)
|
||||
code = append(code, modRM)
|
||||
|
||||
return code
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package x64
|
||||
|
||||
// numRegReg encodes an instruction with up to two registers and a number parameter.
|
||||
func numRegReg(code []byte, reg byte, rm byte, number int, opCode8 byte, opCode32 byte) []byte {
|
||||
// regRegNum encodes an instruction with up to two registers and a number parameter.
|
||||
func regRegNum(code []byte, reg byte, rm byte, number int, opCode8 byte, opCode32 byte) []byte {
|
||||
if sizeOf(number) == 1 {
|
||||
code = regReg(code, reg, rm, opCode8)
|
||||
return append(code, byte(number))
|
@ -9,8 +9,8 @@ import (
|
||||
|
||||
func TestX64(t *testing.T) {
|
||||
assert.DeepEqual(t, x64.Call([]byte{}, 1), []byte{0xe8, 0x01, 0x00, 0x00, 0x00})
|
||||
assert.DeepEqual(t, x64.MoveRegNum32([]byte{}, 0, 1), []byte{0xb8, 0x01, 0x00, 0x00, 0x00})
|
||||
assert.DeepEqual(t, x64.MoveRegNum32([]byte{}, 1, 1), []byte{0xb9, 0x01, 0x00, 0x00, 0x00})
|
||||
assert.DeepEqual(t, x64.MoveRegisterNumber32([]byte{}, 0, 1), []byte{0xb8, 0x01, 0x00, 0x00, 0x00})
|
||||
assert.DeepEqual(t, x64.MoveRegisterNumber32([]byte{}, 1, 1), []byte{0xb9, 0x01, 0x00, 0x00, 0x00})
|
||||
assert.DeepEqual(t, x64.Return([]byte{}), []byte{0xc3})
|
||||
assert.DeepEqual(t, x64.Syscall([]byte{}), []byte{0x0f, 0x05})
|
||||
}
|
||||
|
@ -30,57 +30,57 @@ func (a *Assembler) Finalize() ([]byte, []byte) {
|
||||
case ADD:
|
||||
switch operands := x.Data.(type) {
|
||||
case *RegisterNumber:
|
||||
code = x64.AddRegNum(code, operands.Register, operands.Number)
|
||||
code = x64.AddRegisterNumber(code, operands.Register, operands.Number)
|
||||
case *RegisterRegister:
|
||||
code = x64.AddRegReg(code, operands.Destination, operands.Source)
|
||||
code = x64.AddRegisterRegister(code, operands.Destination, operands.Source)
|
||||
}
|
||||
|
||||
case SUB:
|
||||
switch operands := x.Data.(type) {
|
||||
case *RegisterNumber:
|
||||
code = x64.SubRegNum(code, operands.Register, operands.Number)
|
||||
code = x64.SubRegisterNumber(code, operands.Register, operands.Number)
|
||||
case *RegisterRegister:
|
||||
code = x64.SubRegReg(code, operands.Destination, operands.Source)
|
||||
code = x64.SubRegisterRegister(code, operands.Destination, operands.Source)
|
||||
}
|
||||
|
||||
case MUL:
|
||||
switch operands := x.Data.(type) {
|
||||
case *RegisterNumber:
|
||||
code = x64.MulRegNum(code, operands.Register, operands.Number)
|
||||
code = x64.MulRegisterNumber(code, operands.Register, operands.Number)
|
||||
case *RegisterRegister:
|
||||
code = x64.MulRegReg(code, operands.Destination, operands.Source)
|
||||
code = x64.MulRegisterRegister(code, operands.Destination, operands.Source)
|
||||
}
|
||||
|
||||
case DIV:
|
||||
switch operands := x.Data.(type) {
|
||||
case *RegisterNumber:
|
||||
if operands.Register == x64.RAX {
|
||||
code = x64.PushReg(code, x64.RCX)
|
||||
code = x64.MoveRegNum32(code, x64.RCX, uint32(operands.Number))
|
||||
code = x64.PushRegister(code, x64.RCX)
|
||||
code = x64.MoveRegisterNumber32(code, x64.RCX, uint32(operands.Number))
|
||||
code = x64.ExtendRAXToRDX(code)
|
||||
code = x64.DivReg(code, x64.RCX)
|
||||
code = x64.PopReg(code, x64.RCX)
|
||||
code = x64.DivRegister(code, x64.RCX)
|
||||
code = x64.PopRegister(code, x64.RCX)
|
||||
} else {
|
||||
code = x64.PushReg(code, x64.RAX)
|
||||
code = x64.PushReg(code, x64.RDX)
|
||||
code = x64.MoveRegReg64(code, x64.RAX, operands.Register)
|
||||
code = x64.MoveRegNum32(code, operands.Register, uint32(operands.Number))
|
||||
code = x64.PushRegister(code, x64.RAX)
|
||||
code = x64.PushRegister(code, x64.RDX)
|
||||
code = x64.MoveRegisterRegister64(code, x64.RAX, operands.Register)
|
||||
code = x64.MoveRegisterNumber32(code, operands.Register, uint32(operands.Number))
|
||||
code = x64.ExtendRAXToRDX(code)
|
||||
code = x64.DivReg(code, operands.Register)
|
||||
code = x64.MoveRegReg64(code, operands.Register, x64.RAX)
|
||||
code = x64.PopReg(code, x64.RDX)
|
||||
code = x64.PopReg(code, x64.RAX)
|
||||
code = x64.DivRegister(code, operands.Register)
|
||||
code = x64.MoveRegisterRegister64(code, operands.Register, x64.RAX)
|
||||
code = x64.PopRegister(code, x64.RDX)
|
||||
code = x64.PopRegister(code, x64.RAX)
|
||||
}
|
||||
|
||||
case *RegisterRegister:
|
||||
code = x64.PushReg(code, x64.RAX)
|
||||
code = x64.PushReg(code, x64.RDX)
|
||||
code = x64.MoveRegReg64(code, x64.RAX, operands.Destination)
|
||||
code = x64.PushRegister(code, x64.RAX)
|
||||
code = x64.PushRegister(code, x64.RDX)
|
||||
code = x64.MoveRegisterRegister64(code, x64.RAX, operands.Destination)
|
||||
code = x64.ExtendRAXToRDX(code)
|
||||
code = x64.DivReg(code, operands.Source)
|
||||
code = x64.MoveRegReg64(code, operands.Destination, x64.RAX)
|
||||
code = x64.PopReg(code, x64.RDX)
|
||||
code = x64.PopReg(code, x64.RAX)
|
||||
code = x64.DivRegister(code, operands.Source)
|
||||
code = x64.MoveRegisterRegister64(code, operands.Destination, x64.RAX)
|
||||
code = x64.PopRegister(code, x64.RDX)
|
||||
code = x64.PopRegister(code, x64.RAX)
|
||||
}
|
||||
|
||||
case CALL:
|
||||
@ -121,10 +121,10 @@ func (a *Assembler) Finalize() ([]byte, []byte) {
|
||||
case MOVE:
|
||||
switch operands := x.Data.(type) {
|
||||
case *RegisterNumber:
|
||||
code = x64.MoveRegNum32(code, operands.Register, uint32(operands.Number))
|
||||
code = x64.MoveRegisterNumber32(code, operands.Register, uint32(operands.Number))
|
||||
|
||||
case *RegisterRegister:
|
||||
code = x64.MoveRegReg64(code, operands.Destination, operands.Source)
|
||||
code = x64.MoveRegisterRegister64(code, operands.Destination, operands.Source)
|
||||
}
|
||||
|
||||
case RETURN:
|
||||
|
@ -71,28 +71,6 @@ func (expr *Expression) EachLeaf(call func(*Expression) error) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// EachOperation iterates through all the operations in the tree.
|
||||
func (expr *Expression) EachOperation(call func(*Expression) error) error {
|
||||
if expr.IsLeaf() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Don't descend into the parameters of function calls
|
||||
if expr.Token.Text() == "λ" {
|
||||
return call(expr)
|
||||
}
|
||||
|
||||
for _, child := range expr.Children {
|
||||
err := child.EachOperation(call)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return call(expr)
|
||||
}
|
||||
|
||||
// RemoveChild removes a child from the expression.
|
||||
func (expr *Expression) RemoveChild(child *Expression) {
|
||||
for i, c := range expr.Children {
|
||||
|
Loading…
Reference in New Issue
Block a user