diff --git a/src/build/Function.go b/src/build/Function.go index f99bc2d..a7b0847 100644 --- a/src/build/Function.go +++ b/src/build/Function.go @@ -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) diff --git a/src/build/VariableDefinition.go b/src/build/VariableDefinition.go index 1043143..29a7899 100644 --- a/src/build/VariableDefinition.go +++ b/src/build/VariableDefinition.go @@ -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") diff --git a/src/build/arch/arm64/Registers.go b/src/build/arch/arm64/Registers.go new file mode 100644 index 0000000..39c87b6 --- /dev/null +++ b/src/build/arch/arm64/Registers.go @@ -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} diff --git a/src/build/arch/arm64/Syscall.go b/src/build/arch/arm64/Syscall.go deleted file mode 100644 index fb6495b..0000000 --- a/src/build/arch/arm64/Syscall.go +++ /dev/null @@ -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} diff --git a/src/build/arch/x64/Registers.go b/src/build/arch/x64/Registers.go index ac47f67..da154af 100644 --- a/src/build/arch/x64/Registers.go +++ b/src/build/arch/x64/Registers.go @@ -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} diff --git a/src/build/asm/Assembler.go b/src/build/asm/Assembler.go index e2e1483..7c0ed62 100644 --- a/src/build/asm/Assembler.go +++ b/src/build/asm/Assembler.go @@ -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 +} diff --git a/src/build/cpu/CPU.go b/src/build/cpu/CPU.go index 7e28e22..f6a6f9b 100644 --- a/src/build/cpu/CPU.go +++ b/src/build/cpu/CPU.go @@ -20,8 +20,8 @@ func (c *CPU) IsFree(reg Register) bool { return c.usage&(1<