From 597cb9abed201793a88fc67942dc56d6e451b039 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Mon, 24 Jun 2024 14:14:07 +0200 Subject: [PATCH] Implemented addition --- examples/hello/hello.q | 7 +++++-- src/build/Function.go | 10 ++++++++++ src/build/arch/x64/Add.go | 18 ++++++++++++++++++ src/build/asm/Assembler.go | 27 ++++++++++++++++++--------- src/build/asm/Instructions.go | 11 +++++++++++ src/build/asm/Mnemonic.go | 28 ++++++++++++++++------------ 6 files changed, 78 insertions(+), 23 deletions(-) create mode 100644 src/build/arch/x64/Add.go diff --git a/examples/hello/hello.q b/examples/hello/hello.q index a9ef287..126c5b5 100644 --- a/examples/hello/hello.q +++ b/examples/hello/hello.q @@ -5,8 +5,11 @@ main() { hello() { write := 1 stdout := 1 - address := 4194305 - length := 3 + address := 4194304 + length := 0 + + address += 1 + length += 3 loop { syscall(write, stdout, address, length) diff --git a/src/build/Function.go b/src/build/Function.go index dfce655..2e82577 100644 --- a/src/build/Function.go +++ b/src/build/Function.go @@ -113,6 +113,16 @@ func (f *Function) CompileInstruction(line token.List) error { return f.CompileFunctionCall(expr) } + if expr.Token.Kind == token.Operator { + switch expr.Token.Text() { + case "+=": + name := expr.Children[0].Token.Text() + number, _ := strconv.Atoi(expr.Children[1].Token.Text()) + f.Assembler.AddRegisterNumber(f.Variables[name].Register, uint64(number)) + return nil + } + } + return errors.New(&errors.InvalidInstruction{Instruction: expr.Token.Text()}, f.File, expr.Token.Position) } diff --git a/src/build/arch/x64/Add.go b/src/build/arch/x64/Add.go new file mode 100644 index 0000000..234142b --- /dev/null +++ b/src/build/arch/x64/Add.go @@ -0,0 +1,18 @@ +package x64 + +import "git.akyoto.dev/cli/q/src/build/cpu" + +// AddRegNum8 adds a byte to the given register. +func AddRegNum8(code []byte, destination cpu.Register, number uint8) []byte { + if destination >= 8 { + code = append(code, REX(0, 0, 0, 1)) + destination -= 8 + } + + return append( + code, + 0x83, + ModRM(0b11, 0b000, byte(destination)), + byte(number), + ) +} diff --git a/src/build/asm/Assembler.go b/src/build/asm/Assembler.go index f14ca7c..5eb7b2b 100644 --- a/src/build/asm/Assembler.go +++ b/src/build/asm/Assembler.go @@ -27,21 +27,15 @@ func (a *Assembler) Finalize() ([]byte, []byte) { for _, x := range a.Instructions { switch x.Mnemonic { - case MOVE: + case ADD: switch operands := x.Data.(type) { case *RegisterNumber: - code = x64.MoveRegNum32(code, operands.Register, uint32(operands.Number)) + code = x64.AddRegNum8(code, operands.Register, uint8(operands.Number)) case *RegisterRegister: - code = x64.MoveRegReg64(code, operands.Destination, operands.Source) + // code = x64.AddRegReg64(code, operands.Destination, operands.Source) } - case RETURN: - code = x64.Return(code) - - case SYSCALL: - code = x64.Syscall(code) - case CALL: code = x64.Call(code, 0x00_00_00_00) size := 4 @@ -77,6 +71,21 @@ func (a *Assembler) Finalize() ([]byte, []byte) { case LABEL: labels[x.Data.(*Label).Name] = Address(len(code)) + case MOVE: + switch operands := x.Data.(type) { + case *RegisterNumber: + code = x64.MoveRegNum32(code, operands.Register, uint32(operands.Number)) + + case *RegisterRegister: + code = x64.MoveRegReg64(code, operands.Destination, operands.Source) + } + + case RETURN: + code = x64.Return(code) + + case SYSCALL: + code = x64.Syscall(code) + default: panic("Unknown mnemonic: " + x.Mnemonic.String()) } diff --git a/src/build/asm/Instructions.go b/src/build/asm/Instructions.go index 3662595..091b9d4 100644 --- a/src/build/asm/Instructions.go +++ b/src/build/asm/Instructions.go @@ -2,6 +2,17 @@ package asm import "git.akyoto.dev/cli/q/src/build/cpu" +// AddRegisterNumber adds a number to the given register. +func (a *Assembler) AddRegisterNumber(reg cpu.Register, number uint64) { + a.Instructions = append(a.Instructions, Instruction{ + Mnemonic: ADD, + Data: &RegisterNumber{ + Register: reg, + Number: number, + }, + }) +} + // MoveRegisterNumber moves a number into the given register. func (a *Assembler) MoveRegisterNumber(reg cpu.Register, number uint64) { a.Instructions = append(a.Instructions, Instruction{ diff --git a/src/build/asm/Mnemonic.go b/src/build/asm/Mnemonic.go index a711a0b..55f1dba 100644 --- a/src/build/asm/Mnemonic.go +++ b/src/build/asm/Mnemonic.go @@ -4,17 +4,30 @@ type Mnemonic uint8 const ( NONE Mnemonic = iota + ADD + CALL + JUMP + LABEL MOVE RETURN SYSCALL - LABEL - CALL - JUMP ) // String returns a human readable version. func (m Mnemonic) String() string { switch m { + case ADD: + return "add" + + case CALL: + return "call" + + case JUMP: + return "jump" + + case LABEL: + return "label" + case MOVE: return "move" @@ -23,15 +36,6 @@ func (m Mnemonic) String() string { case SYSCALL: return "syscall" - - case LABEL: - return "label" - - case CALL: - return "call" - - case JUMP: - return "jump" } return "NONE"