Added call registers

This commit is contained in:
Eduard Urbach 2024-06-27 14:25:53 +02:00
parent 735057ac74
commit dc497ba4fb
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
8 changed files with 53 additions and 44 deletions

View File

@ -1,8 +1,4 @@
main() { main() {
hello()
}
hello() {
address := 0 address := 0
length := 0 length := 0
@ -15,6 +11,7 @@ hello() {
length *= 10 length *= 10
length /= 100 length /= 100
length = (0 + 50 - 20) * 10 / 100 length = (0 + 50 - 20) * 10 / 100
length = 1
loop { loop {
print(address, length) print(address, length)
@ -22,7 +19,7 @@ hello() {
} }
print(address, length) { print(address, length) {
write(1, address, length) write(length, address, length+1)
} }
write(fd, address, length) { write(fd, address, length) {

View File

@ -33,6 +33,32 @@ func (f *Function) Execute(operation token.Token, register cpu.Register, value *
return f.ExecuteRegisterRegister(operation, register, temporary) return f.ExecuteRegisterRegister(operation, register, temporary)
} }
// ExecuteFunctionCall executes a function call.
func (f *Function) ExecuteFunctionCall(expr *expression.Expression) error {
funcName := expr.Children[0].Token.Text()
parameters := expr.Children[1:]
if funcName == "syscall" {
err := f.ExpressionsToRegisters(parameters, f.CPU.Syscall)
if err != nil {
return err
}
f.Assembler.Syscall()
} else {
err := f.ExpressionsToRegisters(parameters, f.CPU.Call)
if err != nil {
return err
}
f.Assembler.Call(funcName)
}
return nil
}
// ExecuteLeaf performs an operation on a register with the given leaf operand. // ExecuteLeaf performs an operation on a register with the given leaf operand.
func (f *Function) ExecuteLeaf(operation token.Token, register cpu.Register, operand token.Token) error { func (f *Function) ExecuteLeaf(operation token.Token, register cpu.Register, operand token.Token) error {
switch operand.Kind { switch operand.Kind {

View File

@ -113,7 +113,7 @@ func (f *Function) CompileInstruction(line token.List) error {
} }
if isFunctionCall(expr) { if isFunctionCall(expr) {
return f.CompileFunctionCall(expr) return f.ExecuteFunctionCall(expr)
} }
return errors.New(&errors.InvalidInstruction{Instruction: expr.Token.Text()}, f.File, expr.Token.Position) return errors.New(&errors.InvalidInstruction{Instruction: expr.Token.Text()}, f.File, expr.Token.Position)
@ -139,6 +139,19 @@ func (f *Function) ExpressionToRegister(root *expression.Expression, register cp
return f.Execute(operation, register, right) return f.Execute(operation, register, right)
} }
// ExpressionsToRegisters moves multiple expressions into the specified registers.
func (f *Function) ExpressionsToRegisters(expressions []*expression.Expression, registers []cpu.Register) error {
for i := len(expressions) - 1; i >= 0; i-- {
err := f.ExpressionToRegister(expressions[i], registers[i])
if err != nil {
return err
}
}
return nil
}
// TokenToRegister moves a token into a register. // TokenToRegister moves a token into a register.
// It only works with identifiers, numbers and strings. // It only works with identifiers, numbers and strings.
func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error { func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {

View File

@ -1,32 +0,0 @@
package build
import (
"git.akyoto.dev/cli/q/src/build/expression"
)
// CompileFunctionCall compiles a top-level function call.
func (f *Function) CompileFunctionCall(expr *expression.Expression) error {
funcName := expr.Children[0].Token.Text()
parameters := expr.Children[1:]
registers := f.CPU.Syscall
if funcName != "syscall" {
registers = registers[1:]
}
for i := len(parameters) - 1; i >= 0; i-- {
err := f.ExpressionToRegister(parameters[i], registers[i])
if err != nil {
return err
}
}
if funcName == "syscall" {
f.Assembler.Syscall()
} else {
f.Assembler.Call(funcName)
}
return nil
}

View File

@ -29,12 +29,12 @@ func (f *Function) CompileVariableDefinition(expr *expression.Expression) error
return err return err
} }
f.CPU.Use(reg) variable := &Variable{
f.Variables[name] = &Variable{
Name: name, Name: name,
Register: reg, Register: reg,
} }
f.Variables[name] = variable
f.CPU.Use(reg)
return nil return nil
} }

View File

@ -21,6 +21,9 @@ const (
R15 R15
) )
var GeneralRegisters = []cpu.Register{RBX, RBP, R12, R13, R14, R15} var (
var SyscallRegisters = []cpu.Register{RAX, RDI, RSI, RDX, R10, R8, R9} CallRegisters = []cpu.Register{RDI, RSI, RDX, RCX, R8, R9}
var ReturnValueRegisters = []cpu.Register{RAX, RCX, R11} GeneralRegisters = []cpu.Register{RBX, RBP, R12, R13, R14, R15}
SyscallRegisters = []cpu.Register{RAX, RDI, RSI, RDX, R10, R8, R9}
ReturnValueRegisters = []cpu.Register{RAX, RCX, R11}
)

View File

@ -2,6 +2,7 @@ package cpu
// CPU represents the processor. // CPU represents the processor.
type CPU struct { type CPU struct {
Call []Register
General []Register General []Register
Syscall []Register Syscall []Register
Return []Register Return []Register

View File

@ -225,6 +225,7 @@ func scanFile(path string, functions chan<- *Function) error {
} }
cpu := cpu.CPU{ cpu := cpu.CPU{
Call: x64.CallRegisters,
General: x64.GeneralRegisters, General: x64.GeneralRegisters,
Syscall: x64.SyscallRegisters, Syscall: x64.SyscallRegisters,
Return: x64.ReturnValueRegisters, Return: x64.ReturnValueRegisters,