From c8045cb4fb248d47c1f160e03bc0bd40dcc2428d Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Sun, 4 Aug 2024 00:35:33 +0200 Subject: [PATCH] Improved division --- src/build/asm/Finalize.go | 32 +++++++++++++-- src/build/asm/divide.go | 54 ------------------------- src/build/core/ExecuteRegisterNumber.go | 10 ++++- 3 files changed, 36 insertions(+), 60 deletions(-) delete mode 100644 src/build/asm/divide.go diff --git a/src/build/asm/Finalize.go b/src/build/asm/Finalize.go index ff0c7b3..093e060 100644 --- a/src/build/asm/Finalize.go +++ b/src/build/asm/Finalize.go @@ -58,7 +58,34 @@ func (a Assembler) Finalize() ([]byte, []byte) { } case DIV: - code = divide(code, x.Data) + switch operands := x.Data.(type) { + case *RegisterRegister: + if operands.Destination != x64.RAX { + code = x64.MoveRegisterRegister(code, x64.RAX, operands.Destination) + } + + code = x64.ExtendRAXToRDX(code) + code = x64.DivRegister(code, operands.Source) + + if operands.Destination != x64.RAX { + code = x64.MoveRegisterRegister(code, operands.Destination, x64.RAX) + } + } + + case MODULO: + switch operands := x.Data.(type) { + case *RegisterRegister: + if operands.Destination != x64.RAX { + code = x64.MoveRegisterRegister(code, x64.RAX, operands.Destination) + } + + code = x64.ExtendRAXToRDX(code) + code = x64.DivRegister(code, operands.Source) + + if operands.Destination != x64.RDX { + code = x64.MoveRegisterRegister(code, operands.Destination, x64.RDX) + } + } case CALL: code = x64.Call(code, 0x00_00_00_00) @@ -144,9 +171,6 @@ func (a Assembler) Finalize() ([]byte, []byte) { code = x64.LoadRegister(code, operands.Register, operands.Address.Offset, operands.Address.Length, operands.Address.Base) } - case MODULO: - code = modulo(code, x.Data) - case MOVE: switch operands := x.Data.(type) { case *RegisterNumber: diff --git a/src/build/asm/divide.go b/src/build/asm/divide.go deleted file mode 100644 index a916cad..0000000 --- a/src/build/asm/divide.go +++ /dev/null @@ -1,54 +0,0 @@ -package asm - -import "git.akyoto.dev/cli/q/src/build/arch/x64" - -// divide implements the division on x64 machines. -func divide(code []byte, data any) []byte { - switch operands := data.(type) { - case *RegisterNumber: - if operands.Register == x64.RAX { - code = x64.MoveRegisterNumber(code, x64.RCX, operands.Number) - code = x64.ExtendRAXToRDX(code) - code = x64.DivRegister(code, x64.RCX) - } else { - code = x64.MoveRegisterRegister(code, x64.RAX, operands.Register) - code = x64.MoveRegisterNumber(code, operands.Register, operands.Number) - code = x64.ExtendRAXToRDX(code) - code = x64.DivRegister(code, operands.Register) - code = x64.MoveRegisterRegister(code, operands.Register, x64.RAX) - } - - case *RegisterRegister: - if operands.Destination == x64.RAX { - code = x64.ExtendRAXToRDX(code) - code = x64.DivRegister(code, operands.Source) - } else { - code = x64.MoveRegisterRegister(code, x64.RAX, operands.Destination) - code = x64.ExtendRAXToRDX(code) - - code = x64.DivRegister(code, operands.Source) - code = x64.MoveRegisterRegister(code, operands.Destination, x64.RAX) - } - } - return code -} - -// modulo calculates the division remainder on x64 machines. -func modulo(code []byte, data any) []byte { - switch operands := data.(type) { - case *RegisterNumber: - code = x64.MoveRegisterRegister(code, x64.RAX, operands.Register) - code = x64.MoveRegisterNumber(code, operands.Register, operands.Number) - code = x64.ExtendRAXToRDX(code) - code = x64.DivRegister(code, operands.Register) - code = x64.MoveRegisterRegister(code, operands.Register, x64.RDX) - - case *RegisterRegister: - code = x64.MoveRegisterRegister(code, x64.RAX, operands.Destination) - code = x64.ExtendRAXToRDX(code) - code = x64.DivRegister(code, operands.Source) - code = x64.MoveRegisterRegister(code, operands.Destination, x64.RDX) - } - - return code -} diff --git a/src/build/core/ExecuteRegisterNumber.go b/src/build/core/ExecuteRegisterNumber.go index c78fe66..1884d51 100644 --- a/src/build/core/ExecuteRegisterNumber.go +++ b/src/build/core/ExecuteRegisterNumber.go @@ -24,10 +24,16 @@ func (f *Function) ExecuteRegisterNumber(operation token.Token, register cpu.Reg f.RegisterNumber(asm.MUL, register, number) case token.Div, token.DivAssign: - f.RegisterNumber(asm.DIV, register, number) + tmp := f.NewRegister() + f.RegisterNumber(asm.MOVE, tmp, number) + f.RegisterRegister(asm.DIV, register, tmp) + f.FreeRegister(tmp) case token.Mod, token.ModAssign: - f.RegisterNumber(asm.MODULO, register, number) + tmp := f.NewRegister() + f.RegisterNumber(asm.MOVE, tmp, number) + f.RegisterRegister(asm.MODULO, register, tmp) + f.FreeRegister(tmp) case token.And, token.AndAssign: f.RegisterNumber(asm.AND, register, number)