assembler

package module
v0.0.0-...-8a3f4a4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 22, 2025 License: Unlicense Imports: 9 Imported by: 0

README

risc-assembler

A RISC-V assembler written in Go, designed to convert RISC-V assembly code into executable ELF binary files.

Features

  • Support for RISC-V instructions
  • ELF file generation
  • Integrated preprocessor
  • Instruction encoding
  • Unit tests for main components

Installation

To install the library in your project:

go get github.com/RISC-GoV/risc-assembler

Usage

After installation, you can use the assembler programmatically in Go:

API Functions
- assembler.Assembler.Assemble(filename string, outputFolder string) error

Assembles the RISC-V assembly file at filename and writes an ELF binary to outputFolder or returns an error.

- assembler.Assembler.AssembleLine(line string) ([]byte, error)

Assembles the RISC-V assembly string line and returns its corresponding byte code or an error.

- assembler.Preprocess(file *os.File) []string

Processes macros and directives in the source file and returns cleaned instructions.

- assembler.PreprocessLine(line string) []string

Processes macros and directives in line and returns cleaned instructions.

- assembler.BuildELFFile(program Program) *[]byte

Wraps machine code into a valid ELF binary format.

Example: Assembling a RISC-V file

package main

import (
    "github.com/RISC-GoV/risc-assembler/assembler"
    "os"
)

func main() {
    err := assembler.Assemble("input.asm", "output.elf")
    if err != nil {
        panic(err)
    }
}

Project Structure

  • assembler.go: Core logic of the assembler
  • compiler.go: Compiles instructions into machine code
  • elfbuilder.go: Builds ELF output files
  • preprocesser.go: Handles macros and directives
  • tokens.go: Lexical analysis of instructions
  • encodings.go: Encodes RISC-V instructions
  • defines.go: Constants and shared structures
  • type_encoders.go: Type-specific instruction encoders
  • *.test.go: Unit tests for each component

Documentation

Index

Constants

This section is empty.

Variables

View Source
var InstructionToOpType = map[string]OpPair{

	"lui":   {U, []byte{0b0110111}},
	"auipc": {U, []byte{0b0010111}},

	"jal": {J, []byte{0b1101111}},

	"beq":  {B, []byte{0b1100011, 0x0}},
	"bne":  {B, []byte{0b1100011, 0x1}},
	"blt":  {B, []byte{0b1100011, 0x4}},
	"bge":  {B, []byte{0b1100011, 0x5}},
	"bltu": {B, []byte{0b1100011, 0x6}},
	"bgeu": {B, []byte{0b1100011, 0x7}},

	"jalr":   {I, []byte{0b1100111, 0x0, 0x0}},
	"lb":     {I, []byte{0b0000011, 0x0, 0x0}},
	"lh":     {I, []byte{0b0000011, 0x1, 0x0}},
	"lw":     {I, []byte{0b0000011, 0x2, 0x0}},
	"lbu":    {I, []byte{0b0000011, 0x4, 0x0}},
	"lhu":    {I, []byte{0b0000011, 0x5, 0x0}},
	"sb":     {S, []byte{0b0100011, 0x0, 0x0}},
	"sh":     {S, []byte{0b0100011, 0x1, 0x0}},
	"sw":     {S, []byte{0b0100011, 0x2, 0x0}},
	"addi":   {I, []byte{0b0010011, 0x0, 0x0}},
	"slti":   {I, []byte{0b0010011, 0x2, 0x0}},
	"sltiu":  {I, []byte{0b0010011, 0x3, 0x0}},
	"xori":   {I, []byte{0b0010011, 0x4, 0x0}},
	"ori":    {I, []byte{0b0010011, 0x6, 0x0}},
	"andi":   {I, []byte{0b0010011, 0x7, 0x0}},
	"slli":   {I, []byte{0b0010011, 0x1, 0x00}},
	"srli":   {I, []byte{0b0010011, 0x5, 0x00}},
	"srai":   {I, []byte{0b0010011, 0x5, 0x20}},
	"ebreak": {I, []byte{0b1110011, 0x0, 0x1}},
	"ecall":  {I, []byte{0b1110011, 0x0, 0x0}},

	"add":  {R, []byte{0b0110011, 0x0, 0x00}},
	"sub":  {R, []byte{0b0110011, 0x0, 0x20}},
	"sll":  {R, []byte{0b0110011, 0x1, 0x00}},
	"slt":  {R, []byte{0b0110011, 0x2, 0x00}},
	"sltu": {R, []byte{0b0110011, 0x3, 0x00}},
	"xor":  {R, []byte{0b0110011, 0x4, 0x00}},
	"srl":  {R, []byte{0b0110011, 0x5, 0x00}},
	"sra":  {R, []byte{0b0110011, 0x5, 0x20}},
	"or":   {R, []byte{0b0110011, 0x6, 0x00}},
	"and":  {R, []byte{0b0110011, 0x7, 0x00}},
	"nop":  {R, []byte{0b0000000, 0x0, 0x0}},

	"c.add": {CR, []byte{0b000000, 0b000, 0b000, 0b000, 0b000, 0b0110011}},
	"c.sub": {CR, []byte{0b000000, 0b000, 0b000, 0b000, 0b001, 0b0110011}},
	"c.nop": {CR, []byte{0b000000, 0b000, 0b000, 0b000, 0b001, 0b0000000}},
	"c.j":   {CJ, []byte{0b1100011}},
	"c.jal": {CJ, []byte{0b1101111}},
	"c.beq": {CB, []byte{0b000000}},
	"c.bne": {CB, []byte{0b000001}},
	"c.lw":  {CL, []byte{0b000001}},
	"c.sw":  {CS, []byte{0b000001}},
}
View Source
var PseudoToInstruction = map[string]func([]string) []string{
	"mv":  handleMV,
	"j":   handleJ,
	"jal": handleJAL,
	"jr":  handleJR,
	"add": handleADD,
	"sub": handleSUB,
	"ble": handleBLE,
	"li":  handleLI,
	"la":  handleLA,
	"ret": handleRET,
	"nop": handleNOP,
}

PseudoToInstruction here we handle both pseudo instructions and compressed ones since current cpu is not capable of running compressed instruction we decompress them

Functions

func BuildELFFile

func BuildELFFile(program Program) *[]byte

func GenerateELFHeaders

func GenerateELFHeaders(e_entry [4]byte, e_phnum [2]byte) *[0x34]byte

func GenerateSingleELFProgramHeader

func GenerateSingleELFProgramHeader(htype byte, offset [4]byte, size [4]byte, memoffset [4]byte) *[0x20]byte

func LexBType

func LexBType(strArr []string, parent *Token) error

func LexIType

func LexIType(strArr []string, parent *Token) error

func LexJType

func LexJType(strArr []string, parent *Token) error

func LexSType

func LexSType(strArr []string, parent *Token) error

func LexUType

func LexUType(strArr []string, parent *Token) error

func ParseRegisters

func ParseRegisters(strArr []string, parent *Token) error

func Preprocess

func Preprocess(file *os.File) []string

func PreprocessLine

func PreprocessLine(line string) []string

func TranslateBType

func TranslateBType(opcode int, func3 int, rs1 int, rs2 int, imm int) uint32

func TranslateIType

func TranslateIType(opcode int, rd int, func3 int, rs1 int, imm int) uint32

func TranslateJType

func TranslateJType(opcode int, rd int, imm int) uint32

func TranslateRType

func TranslateRType(opcode int, rd int, func3 int, rs1 int, rs2 int, func7 int) uint32

func TranslateSType

func TranslateSType(opcode int, func3 int, rs1 int, rs2 int, imm int) uint32

func TranslateUType

func TranslateUType(opcode int, rd int, imm int) uint32

Types

type Assembler

type Assembler struct {
	Token *Token
	// contains filtered or unexported fields
}

func (*Assembler) Assemble

func (a *Assembler) Assemble(filename string, outputFolder string) error

func (*Assembler) AssembleLine

func (a *Assembler) AssembleLine(line string) ([]byte, error)

func (*Assembler) Parse

func (a *Assembler) Parse(lineParts []string, parent *Token) (*Token, error)

type Compilation

type Compilation struct {
	// contains filtered or unexported fields
}

type Instruction

type Instruction struct {
	// contains filtered or unexported fields
}

type OpCode

type OpCode int
const (
	R OpCode = iota
	I
	S
	B
	U
	J
	CI  // Compressed I-type
	CSS // Compressed S-type
	CL  // Compressed Load
	CJ  // Compressed Jump
	CR  // Compressed R-type
	CB  // Compressed Branch
	CIW // Compressed Immediate Word
	CS  // Compressed Store
)

func (OpCode) String

func (op OpCode) String() string

String method to return the name of OpCode instead of its numeric value

type OpPair

type OpPair struct {
	// contains filtered or unexported fields
}

type Program

type Program struct {
	// contains filtered or unexported fields
}

func (*Program) InstructionToBinary

func (p *Program) InstructionToBinary(t *Token, relativeInstrCount int) (uint32, error)

type Token

type Token struct {
	// contains filtered or unexported fields
}

func NewToken

func NewToken(tokenType TokenType, value string, parent *Token, pair_optional ...*OpPair) *Token

type TokenType

type TokenType int

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL