Improved division

This commit is contained in:
Eduard Urbach 2024-08-04 00:35:33 +02:00
parent f9ff83136a
commit c8045cb4fb
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
3 changed files with 36 additions and 60 deletions

View File

@ -58,7 +58,34 @@ func (a Assembler) Finalize() ([]byte, []byte) {
} }
case DIV: 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: case CALL:
code = x64.Call(code, 0x00_00_00_00) 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) code = x64.LoadRegister(code, operands.Register, operands.Address.Offset, operands.Address.Length, operands.Address.Base)
} }
case MODULO:
code = modulo(code, x.Data)
case MOVE: case MOVE:
switch operands := x.Data.(type) { switch operands := x.Data.(type) {
case *RegisterNumber: case *RegisterNumber:

View File

@ -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
}

View File

@ -24,10 +24,16 @@ func (f *Function) ExecuteRegisterNumber(operation token.Token, register cpu.Reg
f.RegisterNumber(asm.MUL, register, number) f.RegisterNumber(asm.MUL, register, number)
case token.Div, token.DivAssign: 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: 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: case token.And, token.AndAssign:
f.RegisterNumber(asm.AND, register, number) f.RegisterNumber(asm.AND, register, number)