Improved assembler
This commit is contained in:
parent
e23c1ece80
commit
68ec1467ef
@ -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)
|
||||
|
@ -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")
|
||||
|
39
src/build/arch/arm64/Registers.go
Normal file
39
src/build/arch/arm64/Registers.go
Normal 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}
|
@ -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}
|
@ -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}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user