Specs
- supports blueprints
- supports copy & paste
- supports multiplayer
- supports quality
- supports Informatron and Booktorio in-game wiki
- in-game debugger with breakpoints
- 256 instructions for whole program
- 64 general purpose registers
- 4096 LIFO stack for subprogram calls and local variables
- 4 memory channels for vector processing
- integrated access to the logistic network
- 50+ opcodes
- rich math instructions, trigonometry, rounding
- SIMD instructions, min, max, filter, comparison, etc...
- two input wires (Red, Green)
- two output wires (Red, Green) have same output signals and values
- parallel output, allows output multiple signals simultaneously
- could be controlled through special input signals (interruptions)
- one tick = one instruction (except for SIMD ones)
- made for geeks
Description
fCPU is a combinator that includes:
- program text
- a set of registers (for storing signals or\and numbers)
- couple of memory channels (for storing not zero signals and numbers)
- processor (command processor and vector coprocessor)
Program
Programs for fCPU are entered in plain text in simplified assembly language (this guide is enough for a quick study) and consists of lines.
Each line represents one instruction.
An instruction consists of mnemonics and operands.
For example: mov out1 123[item=copper-ore], here mov is a mnemonic, out1 is the first operand, 123[item=copper-ore] is the second operand.
This instruction tells the processor to send signal [item=copper-ore] with number 123 on to wires connected to the output.
Mnemonics are abbreviated names of operations that the processor understands and knows how to execute.
Operands are arguments to operations. They are used to indicate the values on which an operation will be performed.
The following can be used as operands:
- Signal: each signal consists of a type and a value (123[item=copper-ore])
123 - signal value represented by number
[item=copper-ore] - type can be represented by pictogram or text
- Register: this is a special cell that store the transmitted signal indefinitely (reg1, r2, ...)
- Local: this is a special local cell that store the transmitted signal inside procedure call (var1, v2, ...)
- Memory channel: one memory channel consists of multiple cells (array) that store the signal indefinitely (mem1, m2, ...)
- LogNet channel: receives content of a logistic network this fCPU is placed in (lgn[1], lgn@2, logi[34], ...)
- Input wire: you can receive signals on wires connected to a combinator's input (red, green, red1, green@3, ...)
- Output wire: sets the values at the output of a combinator (out1, out2, ..., out256)
- Address: instruction address (line number 34)
- Label in the code: written in text with a colon in front (:label, :anyname, ...)
The processor executes instructions from a written program in turn, line by line.
Registers
There are 8 generic purpose read/write registers, named reg1, ... reg8 or alias r1, ... r8.
Each register store signal type and numeric value (floating point numbers are supported).
For example mov reg2 10[item=iron-plate], this instruction assigns to reg2 value of 10 and type of \[item=iron-plate].
Besides general purpose registers there are some read only registers:
- ipt: current instruction line numer
- clk: clock, value increases every tick
- cnr, cng: signals number on red cnr or green cng input wire
- cnl: count of a various items in lognet, not a sum of its values
- cnm1, ..., cnm4: signals number in memory
- sp, bp: Stack Pointer, Base Pointer
Output registers (write only):
- out1, ..., out256: output registers (only integer values with signal id, all untyped or zero-valued signals will be deleted)
Stack
The stack grows downwards in memory (from higher addresses to lower addresses).
If you want to know how much space left, use sp register (mov r1 sp).
- Type: LIFO (Last In, First Out)
- Size: 4096
Use push and pop mnemonics to write and read from stack.
push r1 r2 r3 shorthand for
```
push r1
push r2
push r3
```
Procedures
Procedure support through the call, ret, enter, and leave mnemonics, with semantics closely resembling x86.
bp stores the address of the beginning of the current function's stack frame, enabling access to local variables.
call saves the return address by pushing it onto the stack, then transfers control to the target label or address. This allows nested and recursive procedure calls.
Same as:
```
push ipt
jmp addr offset
```
ret completes a procedure by popping the return address from the stack and resuming execution at that location.
Same as:
```
pop <temp>
jmp <temp>
```
enter initializes a new stack frame for a procedure. It pushes the current base pointer onto the stack and sets a new base pointer, optionally reserving space for local variables.
Same as:
```
push bp ; save previous base pointer `bp`
mov bp, sp ; set new stack frame base `sp`
sub sp, size ; allocate space for local variables
```
leave reverses the effect of enter by restoring the previous base pointer and adjusting the stack pointer, effectively destroying the current stack frame before returning.
Same as:
```
mov sp, bp ; discard local variables
pop bp ; restore previous base pointer `bp`
```
Stack diagram after some procedure calls.
```
4096
| ... |
| older ipt | `call :fn1`
| | `enter 3`
| old bp |
| var1 | <-- old bp - 1
| ... |
| var3 | <-- old bp - 3
| ... |
| old ipt | `call :fnN`
| | `enter 1`
| actual bp | <-- `bp`
| var1 | <-- bp - 1
| | <-- `sp`
| ... |
1
```
Local variables
Local variables stored on top of a stack and will be unavailable after leave .
To create procedure stack frame for variables use enter 123.
For example:
```
exampleVars:
enter 3
mov var1 1
mov var2 2
mov var3 3
mov r4 v1
mov r5 v2
mov r6 v3
leave
```
Memory
For processing several signals at the same time, the fCPU provides a vector coprocessor that handles SIMD instructions.
Unlike scalar operations, which process a limited number of signals at a time, vector operations can process hundreds of signals in the same amount of time.
fCPU Memory is an analogue of registers but for vector instructions.
There are 4 memory channels available for use.
Each channel consists of multiple memory cells.
Each cell stores a signal type and a numeric value.
Memory channels are addressed: mem1, ..., mem4.
To access one cell: mem2[44] or mem1@3 (see Arrays)
Logistic network (LogNet)
Acts as a single memory channel, except that it is read-only and other obvious limitations.
lgn channel could be xmov'ed into memory channel for manipulations.
Arrays\indirect addressing
Each register, memory channel or logistic network item could be addressed not only by direct name:
- regN (reg1, r2, etc... N is a register index)
- memC\[M] (mem1\[32], m4\[97], etc.. C is a memory channel number, M is a memory cell index)
- lgn\ (lgn\[43], logi\[12], etc... I is a logistic network item index)
But also with indirect pointer:
- reg@R (reg@3, r@7, etc... R is a register index)
- memC@R (mem1@3, mem4@8, etc... R is a register index)
- lgn@R (lgn@2, logi@8, etc... R is a register index)
This allow you to use values in registers as array indices.
For example:
```
mov r1 10[item=iron-plate]
mov r2 20[item=copper-plate]
mov r3 300[item=steel-plate]
mov r5 2
mov r6 r@5 # r6 will be equal to r2, which is 20[item=copper-plate]
mov r4 m1@5 # r4 will be equal to mem1[2]
mov r5 3
mov r7 r@5 # r7 will be equal to r3, which is 300[item=steel-plate]
mov r4 m2@5 # r4 will be equal to mem2[3]
mov r5 5
mov r8 r@5 # r8 will be equal to r5, which is 5
mov r4 m3@5 # r4 will be equal to mem3[5]
```
This approach is also could be used with red, green input wires and memory channels, for example: red@1, green@8, mem1@3.
Control signals, interruptions
You could control fCPU state by wires, not only manually through game GUI.
There are some signals for it:
- [virtual-signal=signal-fcpu-halt]: Halt program execution.
- [virtual-signal=signal-fcpu-run]: Continue running program.
- [virtual-signal=signal-fcpu-step]: Execute current instruction and move to next.
- [virtual-signal=signal-fcpu-sleep]: Sleep specified game ticks. In sleep mode fCPU do not handle interruptions.
- [virtual-signal=signal-fcpu-jump]: Jump to specified line in program.
If fCPU encounter error in program it will output [virtual-signal=signal-fcpu-error] with line number as value.
Mnemonics
Instructions which can be executed one by one on per frame basis.
Each instruction take one or more operands and modify them or state of fCPU.
Legend
- V, value: integer constant in range \[-2^31..2^31), (-3500)
- T, type: signal type, supports specifying quality ([item=iron-ore], [item=copper-plate,quality=rare])
- Q, quality: signal quality only ('epic', [quality=legendary]) WIP
- VT, signal: consists of Value and Type (123[item=copper-ore], 456[item=iron-plate,quality=uncommon])
- R, reference: register, memory cell, local