Improved assembler

This commit is contained in:
Eduard Urbach 2024-06-26 14:14:11 +02:00
parent e23c1ece80
commit 68ec1467ef
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
7 changed files with 85 additions and 46 deletions

View File

@ -155,7 +155,7 @@ func (f *Function) ExpressionToRegister(root *expression.Expression, register cp
return nil return nil
} else { } else {
temporary, _ := f.CPU.FindFree() temporary, _ := f.CPU.FindFree(f.CPU.General)
f.CPU.Use(temporary) f.CPU.Use(temporary)
f.ExpressionToRegister(right, temporary) f.ExpressionToRegister(right, temporary)
f.CPU.Free(temporary) f.CPU.Free(temporary)

View File

@ -32,7 +32,7 @@ func (f *Function) CompileVariableDefinition(expr *expression.Expression) error
return err return err
} }
reg, exists := f.CPU.FindFree() reg, exists := f.CPU.FindFree(f.CPU.General)
if !exists { if !exists {
panic("no free registers") panic("no free registers")

View File

@ -0,0 +1,39 @@
package register
import "git.akyoto.dev/cli/q/src/build/cpu"
const (
X0 cpu.Register = iota
X1
X2
X3
X4
X5
X6
X7
X8
X9
X10
X11
X12
X13
X14
X15
X16
X17
X18
X19
X20
X21
X22
X23
X24
X25
X26
X27
X28
X29
X30
)
var SyscallArgs = []cpu.Register{X8, X0, X1, X2, X3, X4, X5}

View File

@ -1,9 +0,0 @@
package register
import "git.akyoto.dev/cli/q/src/build/cpu"
const (
SyscallReturn = 0
)
var SyscallArgs = []cpu.Register{8, 0, 1, 2, 3, 4, 5}

View File

@ -3,7 +3,7 @@ package x64
import "git.akyoto.dev/cli/q/src/build/cpu" import "git.akyoto.dev/cli/q/src/build/cpu"
const ( const (
RAX = iota RAX cpu.Register = iota
RCX RCX
RDX RDX
RBX RBX
@ -21,8 +21,6 @@ const (
R15 R15
) )
const SyscallReturn = RAX
var GeneralRegisters = []cpu.Register{RBX, RBP, R12, R13, R14, R15} var GeneralRegisters = []cpu.Register{RBX, RBP, R12, R13, R14, R15}
var SyscallRegisters = []cpu.Register{RAX, RDI, RSI, RDX, R10, R8, R9} var SyscallRegisters = []cpu.Register{RAX, RDI, RSI, RDX, R10, R8, R9}
var ReturnValueRegisters = []cpu.Register{RAX, RCX, R11} var ReturnValueRegisters = []cpu.Register{RAX, RCX, R11}

View File

@ -52,36 +52,7 @@ func (a *Assembler) Finalize() ([]byte, []byte) {
} }
case DIV: case DIV:
switch operands := x.Data.(type) { code = divide(code, x.Data)
case *RegisterNumber:
if operands.Register == x64.RAX {
code = x64.PushRegister(code, x64.RCX)
code = x64.MoveRegisterNumber32(code, x64.RCX, uint32(operands.Number))
code = x64.ExtendRAXToRDX(code)
code = x64.DivRegister(code, x64.RCX)
code = x64.PopRegister(code, x64.RCX)
} else {
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.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.PushRegister(code, x64.RAX)
code = x64.PushRegister(code, x64.RDX)
code = x64.MoveRegisterRegister64(code, x64.RAX, operands.Destination)
code = x64.ExtendRAXToRDX(code)
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: case CALL:
code = x64.Call(code, 0x00_00_00_00) code = x64.Call(code, 0x00_00_00_00)
@ -166,3 +137,43 @@ func (a *Assembler) Finalize() ([]byte, []byte) {
func (a *Assembler) Merge(b *Assembler) { func (a *Assembler) Merge(b *Assembler) {
a.Instructions = append(a.Instructions, b.Instructions...) a.Instructions = append(a.Instructions, b.Instructions...)
} }
// divide implements the division on x64 machines.
func divide(code []byte, data any) []byte {
code = x64.PushRegister(code, x64.RDX)
switch operands := data.(type) {
case *RegisterNumber:
if operands.Register == x64.RAX {
code = x64.PushRegister(code, x64.RCX)
code = x64.MoveRegisterNumber32(code, x64.RCX, uint32(operands.Number))
code = x64.ExtendRAXToRDX(code)
code = x64.DivRegister(code, x64.RCX)
code = x64.PopRegister(code, x64.RCX)
} else {
code = x64.PushRegister(code, x64.RAX)
code = x64.MoveRegisterRegister64(code, x64.RAX, operands.Register)
code = x64.MoveRegisterNumber32(code, operands.Register, uint32(operands.Number))
code = x64.ExtendRAXToRDX(code)
code = x64.DivRegister(code, operands.Register)
code = x64.MoveRegisterRegister64(code, operands.Register, x64.RAX)
code = x64.PopRegister(code, x64.RAX)
}
case *RegisterRegister:
if operands.Destination == x64.RAX {
code = x64.ExtendRAXToRDX(code)
code = x64.DivRegister(code, operands.Source)
} else {
code = x64.PushRegister(code, x64.RAX)
code = x64.MoveRegisterRegister64(code, x64.RAX, operands.Destination)
code = x64.ExtendRAXToRDX(code)
code = x64.DivRegister(code, operands.Source)
code = x64.MoveRegisterRegister64(code, operands.Destination, x64.RAX)
code = x64.PopRegister(code, x64.RAX)
}
}
code = x64.PopRegister(code, x64.RDX)
return code
}

View File

@ -20,8 +20,8 @@ func (c *CPU) IsFree(reg Register) bool {
return c.usage&(1<<reg) == 0 return c.usage&(1<<reg) == 0
} }
func (c *CPU) FindFree() (Register, bool) { func (c *CPU) FindFree(registers []Register) (Register, bool) {
for _, reg := range c.General { for _, reg := range registers {
if c.IsFree(reg) { if c.IsFree(reg) {
return reg, true return reg, true
} }