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
} else {
temporary, _ := f.CPU.FindFree()
temporary, _ := f.CPU.FindFree(f.CPU.General)
f.CPU.Use(temporary)
f.ExpressionToRegister(right, temporary)
f.CPU.Free(temporary)

View File

@ -32,7 +32,7 @@ func (f *Function) CompileVariableDefinition(expr *expression.Expression) error
return err
}
reg, exists := f.CPU.FindFree()
reg, exists := f.CPU.FindFree(f.CPU.General)
if !exists {
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"
const (
RAX = iota
RAX cpu.Register = iota
RCX
RDX
RBX
@ -21,8 +21,6 @@ const (
R15
)
const SyscallReturn = RAX
var GeneralRegisters = []cpu.Register{RBX, RBP, R12, R13, R14, R15}
var SyscallRegisters = []cpu.Register{RAX, RDI, RSI, RDX, R10, R8, R9}
var ReturnValueRegisters = []cpu.Register{RAX, RCX, R11}

View File

@ -52,36 +52,7 @@ func (a *Assembler) Finalize() ([]byte, []byte) {
}
case DIV:
switch operands := x.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.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)
}
code = divide(code, x.Data)
case CALL:
code = x64.Call(code, 0x00_00_00_00)
@ -166,3 +137,43 @@ func (a *Assembler) Finalize() ([]byte, []byte) {
func (a *Assembler) Merge(b *Assembler) {
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
}
func (c *CPU) FindFree() (Register, bool) {
for _, reg := range c.General {
func (c *CPU) FindFree(registers []Register) (Register, bool) {
for _, reg := range registers {
if c.IsFree(reg) {
return reg, true
}