mirror of
https://github.com/RoBaertschi/tt.git
synced 2025-04-18 23:13:29 +00:00
116 lines
1.8 KiB
Go
116 lines
1.8 KiB
Go
package amd64
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type Program struct {
|
|
Functions []Function
|
|
}
|
|
|
|
func (p *Program) Emit() string {
|
|
var builder strings.Builder
|
|
|
|
for _, function := range p.Functions {
|
|
builder.WriteString(function.Emit())
|
|
builder.WriteString("\n")
|
|
}
|
|
|
|
return builder.String()
|
|
}
|
|
|
|
type Function struct {
|
|
Name string
|
|
Instructions []Instruction
|
|
}
|
|
|
|
// This calls the main function and uses it's return value to exit
|
|
const executableAsmHeader = "format ELF64 executable\n" +
|
|
"segment readable executable\n" +
|
|
"entry _start\n" +
|
|
"_start:\n" +
|
|
" call main\n" +
|
|
" mov rdi, rax\n" +
|
|
" mov rax, 60\n" +
|
|
" syscall\n"
|
|
|
|
func (f *Function) Emit() string {
|
|
var builder strings.Builder
|
|
|
|
builder.WriteString(executableAsmHeader)
|
|
builder.WriteString(fmt.Sprintf("%s:\n", f.Name))
|
|
|
|
for _, inst := range f.Instructions {
|
|
builder.WriteString(fmt.Sprintf(" %s\n", inst.InstructionString()))
|
|
}
|
|
|
|
return builder.String()
|
|
}
|
|
|
|
type Opcode string
|
|
|
|
const (
|
|
Mov Opcode = "mov"
|
|
Ret Opcode = "ret"
|
|
)
|
|
|
|
type Instruction struct {
|
|
Opcode Opcode
|
|
Lhs Operand
|
|
Rhs Operand
|
|
}
|
|
|
|
func (i *Instruction) InstructionString() string {
|
|
if i.Lhs == nil {
|
|
return fmt.Sprintf("%s", i.Opcode)
|
|
}
|
|
|
|
return fmt.Sprintf("%s %s, %s", i.Opcode, i.Lhs.OperandString(Eight), i.Rhs.OperandString(Eight))
|
|
}
|
|
|
|
type OperandSize int
|
|
|
|
type Operand interface {
|
|
OperandString(OperandSize) string
|
|
}
|
|
|
|
type Register int
|
|
|
|
const (
|
|
AX Register = iota
|
|
R10
|
|
|
|
One OperandSize = iota
|
|
Four
|
|
Eight
|
|
)
|
|
|
|
func (r Register) OperandString(size OperandSize) string {
|
|
switch r {
|
|
case AX:
|
|
switch size {
|
|
case One:
|
|
return "al"
|
|
case Four:
|
|
return "eax"
|
|
}
|
|
return "rax"
|
|
case R10:
|
|
switch size {
|
|
case One:
|
|
return "r10b"
|
|
case Four:
|
|
return "r10d"
|
|
}
|
|
return "r10"
|
|
}
|
|
return "INVALID_REGISTER"
|
|
}
|
|
|
|
type Imm int64
|
|
|
|
func (i Imm) OperandString(size OperandSize) string {
|
|
return fmt.Sprintf("%d", i)
|
|
}
|