Improved assembler

This commit is contained in:
2023-10-23 12:37:20 +02:00
parent a54c62f6e0
commit ab48a86ccd
22 changed files with 329 additions and 139 deletions

106
src/cpu/CPU.go Normal file
View File

@ -0,0 +1,106 @@
package cpu
import "git.akyoto.dev/cli/q/src/register"
// CPU manages the allocation state of registers.
type CPU struct {
All List
General List
Call List
Syscall List
}
// New creates a new CPU state.
func New() *CPU {
// Rather than doing lots of mini allocations
// we'll allocate memory for all registers at once.
registers := [16]Register{
{ID: register.R0},
{ID: register.R1},
{ID: register.R2},
{ID: register.R3},
{ID: register.R4},
{ID: register.R5},
{ID: register.R6},
{ID: register.R7},
{ID: register.R8},
{ID: register.R9},
{ID: register.R10},
{ID: register.R11},
{ID: register.R12},
{ID: register.R13},
{ID: register.R14},
{ID: register.R15},
}
rax := &registers[0]
rcx := &registers[1]
rdx := &registers[2]
rbx := &registers[3]
rsp := &registers[4]
rbp := &registers[5]
rsi := &registers[6]
rdi := &registers[7]
r8 := &registers[8]
r9 := &registers[9]
r10 := &registers[10]
r11 := &registers[11]
r12 := &registers[12]
r13 := &registers[13]
r14 := &registers[14]
r15 := &registers[15]
// Register configuration
return &CPU{
All: List{
rax,
rcx,
rdx,
rbx,
rsp,
rbp,
rsi,
rdi,
r8,
r9,
r10,
r11,
r12,
r13,
r14,
r15,
},
General: List{
rcx,
rbx,
rbp,
r11,
r12,
r13,
r14,
r15,
},
Call: List{
rdi,
rsi,
rdx,
r10,
r8,
r9,
},
Syscall: List{
rax,
rdi,
rsi,
rdx,
r10,
r8,
r9,
},
}
}
// ByID returns the register with the given ID.
func (cpu *CPU) ByID(id register.ID) *Register {
return cpu.All[id]
}

29
src/cpu/List.go Normal file
View File

@ -0,0 +1,29 @@
package cpu
// List is a list of registers.
type List []*Register
// FindFree tries to find a free register
// and returns nil when all are currently occupied.
func (registers List) FindFree() *Register {
for _, register := range registers {
if register.IsFree() {
return register
}
}
return nil
}
// InUse returns a list of registers that are currently in use.
func (registers List) InUse() List {
var inUse List
for _, register := range registers {
if !register.IsFree() {
inUse = append(inUse, register)
}
}
return inUse
}

39
src/cpu/Register.go Normal file
View File

@ -0,0 +1,39 @@
package cpu
import (
"fmt"
"git.akyoto.dev/cli/q/src/errors"
"git.akyoto.dev/cli/q/src/register"
)
// Register represents a single CPU register.
type Register struct {
ID register.ID
user fmt.Stringer
}
// Use marks the register as used by the given object.
func (register *Register) Use(obj fmt.Stringer) error {
if register.user != nil {
return &errors.RegisterInUse{Register: register.ID.String(), User: register.user.String()}
}
register.user = obj
return nil
}
// Free frees the register so that it can be used for new calculations.
func (register *Register) Free() {
register.user = nil
}
// IsFree returns true if the register is not in use.
func (register *Register) IsFree() bool {
return register.user == nil
}
// String returns a human-readable representation of the register.
func (register *Register) String() string {
return fmt.Sprintf("%s%s%v", register.ID, "=", register.user)
}