Skip to content

alexdremov/SPUAsm

Repository files navigation

Assembly-type code translator and SPU-executor

Codacy Badge CodeFactor

Description

This project implements code translation to uneven bytecode, disassembly tool for generated bytecode, and bytecode executor (Soft Processor Unit).

In addition, I implemented code analyser that checks for syntax mistakes. Analyser outputs info in clang format, so most IDEs highlight wrong expressions and provide descriptions of errors as well as possible solutions when possible.

During the translation, .lst file is generated. It provides information about bytecode generation and what command at what offset is located.

Documentation

Installation

Enter project's directory and execute:

mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build .

Three files will be created:

  • SPU - Soft Processor Unit, executes created programs
  • SPUAsm - translates source file (.spus) to binary file (.spub) that can be executed by SPU
  • SPUDisAsm - disassembly for generated binary files

Usage

SPUAsm

$ SPUAsm <source file>
        --input <filename.spus>     - source file (can be specified without --input)
        --output <filename.spub>    - binary assembled file
        -E                          - generate preprocessed file
        --verbose                   - output assembly debug information
        --lst <filename.lst>        - listing file of generated code (assembly.lst by default) 
        -h, --help                  - show help message

SPUDisAsm

$ SPUDisAsm <binary file>
        --input <filename.spub>     - binary assembled file
        --output <filename.spus>    - source file (if not specified, stdout selected)
        --verbose                   - output assembly debug information
        -h, --help                  - show help message

SPU

$ SPU <binary file>
        --input <filename.spub>     - binary assembled file
        --output <filename.spus>    - source file (if not specified, stdout selected)
        --verbose                   - output assembly debug information
        --vsync                     - render vram after every command
        -h, --help                  - show help message

Examples

All examples are available in this dir.

Squares of first n numbers

Show code
;
; Squares
;

in rbx  ; rbx as counter

push 0
pop rax

loop:
dec rbx  ; decrease counter

; Calculating square
push rax
push rax
mul
out

; Prepare for the next loop
pop
inc rax

jm mondayOnly ; exit if it is monday

; Insert conditional jump operands
push 0
push rbx

jne loop

mondayOnly:

Popping circles

Show code
; height 32
; width  64

push 32
push 16
push 10
push 35
call drawCircle

clrscr

push 32
push 16
push 4
push 42
call drawCircle

clrscr

push 16
push 8
push 2
push 42
call drawCircle

clrscr
rend

push 40
push 25
push 4
push 48
call drawCircle

clrscr
rend

push 60
push 13
push 8
push 48
call drawCircle


hlt

drawCircle: ;(x0, y0, r, symbol)
    pop [2]
    pop rcx  ; r
    pop rbx  ; y0
    pop rax  ; x0

    mov rdx 0   ; initial angle
    loop:
        push rbx
        push rdx
        sin
        push rcx
        mul
        add ; y0 + r*sin(alpha)

        pop [0] ; y coordinate

        push rax
        push rdx
        cos
        push rcx
        push 2
        mul
        mul
        add ; x0 + r*cos(alpha)

        pop [1] ; x coordinate

        pixset [1] [0] [2]
        
        rend
        slp 10000
    ; loop params
    mov rdx rdx+0.1
    push rdx
    push 3.1415926535897
    push 2
    mul
    jbe loop
    ret

Square equation solutions

Show code
;
; Data input
; (a, b, c)
;
in      rax
in      rbx
in      rcx

;
; D calculation
;
push    rbx
push    2
pow

push    4
push    rax
mul
push    rcx
mul
sub
sqrt
pop     rdx


;
; First x
;
clear
push    -1
push    rbx
mul
push    rdx
sub
push    2
div
push    rax
div
pop     rcx

;
; Second x
;
clear
push    -1
push    rbx
mul
push    rdx
add
push    2
div
push    rax
div
pop     rax

;
; Output
;
out     rax
out     rcx

Algorithm description

Binary generation can be splitted into several parts:

  • Cleanup
  • Analysis
  • Final cleanup
  • Translation
  • Final checks

If process fails on any part, the next parts are not executed.

Cleanup

Just double whitespaces, trailing/leading whitespaces removed. Operations that does not change code structure, lines number etc.

Analysis

Analyses code for syntax errors, builds temporary code to calculate labels offsets. Prints errors descriptions in clang format.

Final cleanup

All unnecessary indent symbols removed (comments, blank lines, unneded whitespaces). Code structure will be altered, line numbers are not preserved.

Translation

Code is translated using labels table generated on analysis step. At this point, all errors must be catched by analysis, but still some can make thir way to this point. In this case, generation will fail, dumping wrong instruction and its number.

Final checks

Check that all operations completed correctly; labels table is complete and not redundant.

Syntax

Complex value (cvalue)

Operators with arguments accept complex value argument. Argument can be assignable or not assignable

Complex value examples:

  • [rax+5] - assignable, RAM on adress rax+5 with double adressation
  • 4 - not assignable, immediate value 4
  • [5] - assignable, RAM on adress 5 with double adressation
  • [rcx] - assignable, RAM on adress rcx with double adressation
  • rcx - assignable, register rcx
  • (rcx) - assignable, RAM on adress rcx with char adressation
  • (rcx+10) - assignable, RAM on adress rcx+10 with char adressation
  • (10) - assignable, RAM on adress 10 with char adressation

Notice: whitespaces inside complex value are not allowed and considered as syntax error.

General purpose

push

Push value to the stack

pop <nothing/assignable cvalue>

Pop value from the stack

  • no args - just delete
  • cvalue - pop and save to assignable cvalue

in <nothing/assignable cvalue>

Request value from the console

  • no args - push value to the stack
  • cvalue - save to assignable cvalue

out <nothing/any cvalue>

Prints value to the console

  • no args - last stack value
  • cvalue - cvalue value

mov

destination -> source

Sets the first argument value to the secon argument's value

dump

Dump stack information

clear

Clear stack

rend

Force render vram

slp

Sleep for ... nanoseconds

hlt

Finish the program

pixelset

x y value

Set vram pixel (x, y) to value

clrscr

Fill vram with spaces

Math

inc <nothing/assignable cvalue>

Increments the value

  • no args - last stack value
  • cvalue - cvalue value

dec <nothing/assignable cvalue>

Decrements the value

  • no args - last stack value
  • cvalue - cvalue value

add

Add two last stack values and push to the stack

sub

Substract two last stack values and push to the stack

mul

Multiply two last stack values and push to the stack

div

Divide two last stack values and push to the stack

sin

Sin of the last stack value

cos

Cos of the last stack value

abs

Abs of the last stack value

sqrt

Square root of the last stack value

pow

The pre-last element of the stack to the power of the last one

Codeflow modifiers

call

Gives execution to the label block. Can be returned to the call instruction using ret

ret

Returnes to the last call position. May fail if there were no calls.

jmp

Jump to the label

jb

Jump if last element is bigger than pre-last. Removes both operands from the stack

jbe

Jump if last element is bigger-or-equal than pre-last. Removes both operands from the stack

je

Jump if last element is equal to the pre-last one. Removes both operands from the stack

jne

Jump if last element is not equal to the pre-last one. Removes both operands from the stack

ja

Jump if last element is lower than pre-last. Removes both operands from the stack

jae

Jump if last element is lower-or-equal than pre-last. Removes both operands from the stack

jm

Jump if it's Monday.

labelName:

Creates label

Links