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
|
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)
|
||||||
|
@ -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")
|
||||||
|
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"
|
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}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user