Added CPU type

This commit is contained in:
Eduard Urbach 2024-06-21 22:16:42 +02:00
parent 1058970be3
commit 4faa1641c6
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
10 changed files with 92 additions and 28 deletions

View File

@ -18,8 +18,8 @@ func TestErrors(t *testing.T) {
{"ExpectedFunctionDefinition.q", errors.ExpectedFunctionDefinition},
{"ExpectedFunctionName.q", errors.ExpectedFunctionName},
{"ExpectedFunctionParameters.q", errors.ExpectedFunctionParameters},
{"InvalidInstruction-Identifier.q", &errors.InvalidInstruction{Instruction: "abc"}},
{"InvalidInstruction-Number.q", &errors.InvalidInstruction{Instruction: "123"}},
{"InvalidInstructionIdentifier.q", &errors.InvalidInstruction{Instruction: "abc"}},
{"InvalidInstructionNumber.q", &errors.InvalidInstruction{Instruction: "123"}},
{"MissingAssignValue.q", errors.MissingAssignValue},
{"MissingBlockEnd.q", errors.MissingBlockEnd},
{"MissingBlockStart.q", errors.MissingBlockStart},

View File

@ -29,8 +29,8 @@ func Finalize(functions map[string]*Function) ([]byte, []byte) {
func entry() *asm.Assembler {
entry := asm.New()
entry.Call("main")
entry.MoveRegisterNumber(x64.SyscallArgs[0], linux.Exit)
entry.MoveRegisterNumber(x64.SyscallArgs[1], 0)
entry.MoveRegisterNumber(x64.SyscallRegisters[0], linux.Exit)
entry.MoveRegisterNumber(x64.SyscallRegisters[1], 0)
entry.Syscall()
return entry
}

View File

@ -4,8 +4,8 @@ import (
"fmt"
"strconv"
"git.akyoto.dev/cli/q/src/build/arch/x64"
"git.akyoto.dev/cli/q/src/build/asm"
"git.akyoto.dev/cli/q/src/build/cpu"
"git.akyoto.dev/cli/q/src/build/expression"
"git.akyoto.dev/cli/q/src/build/fs"
"git.akyoto.dev/cli/q/src/build/token"
@ -21,6 +21,7 @@ type Function struct {
Body token.List
Variables map[string]*Variable
Assembler asm.Assembler
CPU cpu.CPU
Error error
}
@ -169,12 +170,12 @@ func (f *Function) CompileFunctionCall(expr *expression.Expression) error {
}
n, _ := strconv.Atoi(variable.Value.Token.Text())
f.Assembler.MoveRegisterNumber(x64.SyscallArgs[i], uint64(n))
f.Assembler.MoveRegisterNumber(f.CPU.Syscall[i], uint64(n))
case token.Number:
value := parameter.Token.Text()
n, _ := strconv.Atoi(value)
f.Assembler.MoveRegisterNumber(x64.SyscallArgs[i], uint64(n))
f.Assembler.MoveRegisterNumber(f.CPU.Syscall[i], uint64(n))
default:
panic("Unknown expression")

View File

@ -0,0 +1,28 @@
package x64
import "git.akyoto.dev/cli/q/src/build/cpu"
const (
rax = iota
rcx
rdx
rbx
rsp
rbp
rsi
rdi
r8
r9
r10
r11
r12
r13
r14
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}

View File

@ -1,13 +1,5 @@
package x64
import "git.akyoto.dev/cli/q/src/build/cpu"
const (
SyscallReturn = 0 // rax
)
var SyscallArgs = []cpu.Register{0, 7, 6, 2, 10, 8, 9}
// Syscall is the primary way to communicate with the OS kernel.
func Syscall(code []byte) []byte {
return append(code, 0x0f, 0x05)

View File

@ -4,7 +4,7 @@ import (
"sync"
)
// compile waits for all functions to finish compilation.
// compile waits for the scan to finish and compiles all functions.
func compile(functions <-chan *Function, errors <-chan error) (map[string]*Function, error) {
allFunctions := map[string]*Function{}
@ -28,18 +28,7 @@ func compile(functions <-chan *Function, errors <-chan error) (map[string]*Funct
}
}
wg := sync.WaitGroup{}
for _, function := range allFunctions {
wg.Add(1)
go func() {
defer wg.Done()
function.Compile()
}()
}
wg.Wait()
compileFunctions(allFunctions)
for _, function := range allFunctions {
if function.Error != nil {
@ -49,3 +38,19 @@ func compile(functions <-chan *Function, errors <-chan error) (map[string]*Funct
return allFunctions, nil
}
// compileFunctions starts a goroutine for each function compilation and waits for completion.
func compileFunctions(functions map[string]*Function) {
wg := sync.WaitGroup{}
for _, function := range functions {
wg.Add(1)
go func() {
defer wg.Done()
function.Compile()
}()
}
wg.Wait()
}

31
src/build/cpu/CPU.go Normal file
View File

@ -0,0 +1,31 @@
package cpu
// CPU represents the processor.
type CPU struct {
General []Register
Syscall []Register
Return []Register
usage uint64
}
func (c *CPU) Use(reg Register) {
c.usage |= (1 << reg)
}
func (c *CPU) Free(reg Register) {
c.usage &= ^(1 << reg)
}
func (c *CPU) IsFree(reg Register) bool {
return c.usage&(1<<reg) == 0
}
func (c *CPU) FindFree() (Register, bool) {
for _, reg := range c.General {
if c.IsFree(reg) {
return reg, true
}
}
return 0, false
}

View File

@ -6,6 +6,8 @@ import (
"strings"
"sync"
"git.akyoto.dev/cli/q/src/build/arch/x64"
"git.akyoto.dev/cli/q/src/build/cpu"
"git.akyoto.dev/cli/q/src/build/fs"
"git.akyoto.dev/cli/q/src/build/token"
"git.akyoto.dev/cli/q/src/errors"
@ -225,6 +227,11 @@ func scanFile(path string, functions chan<- *Function) error {
Head: tokens[paramsStart:bodyStart],
Body: tokens[bodyStart : i+1],
Variables: map[string]*Variable{},
CPU: cpu.CPU{
General: x64.GeneralRegisters,
Syscall: x64.SyscallRegisters,
Return: x64.ReturnValueRegisters,
},
}
nameStart = -1