Last active
January 15, 2023 21:28
-
-
Save BasedUser/321b38eb63eee08a376f3b3a3c3e1528 to your computer and use it in GitHub Desktop.
The Mindustry Instruction Set Architecture (revision 2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The Mindustry Logic ISA (mISA, "miss-uh") Manual | |
Revision 2 (2021/II/12) | |
This document describes an ISA capable of being translated into mlog interpretable code. This will also be a good target architecture for any compilers, and a decent ISA for message block (blocks containing up to 220 characters) outputs. | |
As I (router) am unable to describe the hardware's exact requirements to run such code due to lack of experience with hardware engineering, I will define the minimum criteria for interpreting mISA here. | |
---------------- | |
Every variable is 10-bit, or in the case of string literals, 16-bit long for just the header followed by up to 34 (maxTokenLength-2) UTF-8 characters. Every U+000A "\n" (newline) must be interpreted as 2 characters "\" and "n", regardless of line ending and even if "\n" represents one UTF-8 character (which it does). User-addressable registers have a prefix of 0, while enums and constants have a reserved prefix of 1. This means that the variable 1000110111 can be equally interpreted as the user register 567, or the enum @pulverizer - the latter behavior is advised due to the nature of enums. | |
There must be 512 unique, user-addressable registers (aka logic variables) in any processor executing this ISA. The reason for this is the maximum amount of instructions you can store in-game is 1000. To use all 512 registers, say, as individually addressable RAM, you would *really* be storing 511, and with that using up 511*2 + 4 = 1026 instructions, which is just over the limit of 1000 and thus perfectly legal no matter what code is stuffed into an instruction. This isn't to say that you *can't* use more than 512 registers at once: just that this is the minimal amount for ALL code to be valid, and code using more registers can be optimized to ≤512. | |
There are also 512 potential enums and constants defined. Any undefined enums must preserve their value via getting their ID from Vars.constants.vars.get("@enumname") (at build 123, also that class is private - make it public manually and read it). but a select few will be reassigned. The third element in this list is what I mapped these enums to (with their prefix removed). | |
000000000 - the end - false | |
000000001 - false - true | |
000000010 - true - null | |
000000011 - null - @this | |
111111100 - undefined - (constant IEEE754 number header) | |
111111101 - undefined - (string literal header) | |
111111110 - undefined - (constant 64-bit integer header) | |
111111111 - undefined - (constant block link header) | |
However, redefining these can only do so much, due to how fluid Mindustry's code is. The following enums were appended to the end of the list generated by Vars.constants.vars, in the following order to successfully map mlog to mISA. All senseables, other enums must be appended to the list below after @unit. | |
@mapw, @maph, @links, @ipt, @thisx, @thisy, @counter, @time, @unit. | |
I also defined 3 header variables to convey constant values. These would be regular mlog decimals (IEEE754 double-precision), strings (followed by 6 bits encoding length), and integers such as 0xFEDCBA9876543210. | |
This is what a string literal's structure is. Example: "Hi!\n" | |
string length | "H" | "i" | "!" | "\n" | |
11111111 | 10 000101 | 01001000 | 01101001 | 00100001 | 00001010 | |
This is what a block link's structure is. Example: "pulverizer4" | |
blink | benum | uint12+1 | |
11111111 | 11 100011 | 0111 0000 | 00000011 | |
Enum mappings to names are written in the end of this file (with their prefix removed). | |
If there is a 1 after a senseable enum, it is writable. | |
---------------- | |
mISA has 16 instructions with configurable parameters. | |
While describing this architecture, I made the executive decision to reduce three instructions: "end", "uradar", "noop". | |
Any "end" is equivalent "set @counter 0", "uradar" can be mapped back and forth to "radar" with @unit instead of the turret (while this usage won't work in Mindustry, it fits more info into radar), and "noop" is equivalent to "op" with an invalid argument. | |
All opcodes that don't end in a byte-divisible value must be padded with data. | |
For the sake of forwards compatibility with additional instructions AND comments, any metadata starting with 1 will imply a 4bit counter immediately leading it describing how many variables are expected after it. Usually, these variables will be full string literals, the first one starting with "#". If anything else is read, parsing it is considered undefined behavior and should be skipped if the compiler is not completely sure what these strings mean. This may be amended in future mISA revisions. | |
INSTRUCTIONS | |
0000 - op | |
0001 - set | |
0010 - read | |
0011 - write | |
0100 - draw | |
0101 - print | |
0110 - drawflush | |
0111 - printflush | |
1000 - getlink | |
1001 - control | |
1010 - radar | |
1011 - sensor | |
1100 - jump | |
1101 - ubind | |
1110 - ucontrol | |
1111 - ulocate | |
-------------------------------- | |
Syntax | |
All instruction/opcode descriptions will be written as follows: | |
XXXX - instrName | |
These next 2 lines will be examples of full-length instructions, assuming all arguments besides instruction-local enums are user register 0. Different variables are separated by spaces, unless there is a " | ", in which case it's a byte separation. | |
inst en1 | en2 | arg1 | |
XXXX 0000 | 000000 00 | 00000000 | |
A short description of the instrName instruction, sources of local enums. | |
Local enum values (third/fourth argument in mapping description): | |
EVALUE - ENAME - THIRD - FOURTH | |
---------------- | |
0000 - op | |
inst opENUM | arg0 | arg1 | arg2 | |
0000 0000 | 00 000000 |0000 0000 | 000000 00| 00000000 | |
Executes an operation over arg1 and arg2, and stores it in arg0 (by default). Arguments can be omitted depending on local enum. | |
All op enums were taken from LogicOp.all and inserted at position 1, the rest are inserted/appended. | |
However, the `wait` enum refers to a new instruction (as of 125), "wait x". Its argument is the amount of seconds to pause for, in *world time*. | |
Local enum values (third argument - amount of STORED variables following it): | |
000000 - noop0 - 0 | |
000001 - add - 3 | |
000010 - subtract - 3 | |
000011 - mul - 3 | |
000100 - div - 3 | |
000101 - idiv - 3 | |
000110 - mod - 3 | |
000111 - pow - 3 | |
001000 - equal - 3 | |
001001 - notEqual - 3 | |
001010 - land - 3 | |
001011 - lessThan - 3 | |
001100 - lessThanEq - 3 | |
001101 - greaterThanEq - 3 | |
001110 - shl - 3 | |
001111 - shr - 3 | |
010000 - or - 3 | |
010001 - and - 3 | |
010010 - xor - 3 | |
010011 - not - 2 | |
010100 - max - 3 | |
010101 - min - 3 | |
010110 - atan2 - 3 | |
010111 - dst - 3 | |
011000 - noise - 3 | |
011001 - abs - 2 | |
011010 - log - 2 | |
011011 - log10 - 2 | |
011100 - sin - 2 | |
011101 - cos - 2 | |
011110 - tan - 2 | |
011111 - floor - 2 | |
100001 - ceil - 2 | |
100010 - sqrt - 2 | |
100011 - rand - 2 | |
100100 - isNull - 1 | |
100101 - wait - 1 | |
111101 - noop3 - 3 | |
111110 - noop2 - 2 | |
111111 - noop1 - 1 | |
others - noop0 - 0 | |
---------------- | |
0001 - set | |
inst arg0 | arg1 | |
0001 0000 | 000000 00 | 00000000 | |
Sets arg0's value to arg1. | |
No local enums. | |
---------------- | |
0010 - read | |
inst arg0 | arg1 | arg2 | | |
0010 0000 | 000000 00 | 00000000 | 00000000 | 00 000000 | |
Sets arg0's value to whatever value was at address arg2 in the memory cell arg1. | |
No local enums. | |
---------------- | |
0011 - write | |
inst arg0 | arg1 | arg2 | | |
0010 0000 | 000000 00 | 00000000 | 00000000 | 00 000000 | |
Writes arg0's value to address arg2 in the memory cell arg1. | |
No local enums. | |
---------------- | |
0100 - draw | |
inst op | B| arg0 | arg1 | arg2 | arg3 | arg4 | arg5 | | |
0100 0000 | 0 0000000 | 000 00000 | 00000 000 | 0000000 0 | 00000000 | 0 0000000 | 000 00000 | 00000 000 | |
Appends a drawing instruction to the draw buffer of this processor. Arguments can be omitted depending on enum. HOWEVER, if the "op" is an invalid draw operation (such as noop), the B flag is NOT stored, and the draw instruction terminates. Arguments may be omitted depending on local enum. | |
If the B flag is set, all enum variables (1XXXXXXXXX) will be treated as integers 0-511. | |
If the draw buffer is full, this instruction will be skipped. | |
Enums gathered from in-game. | |
Local enum values (third argument - amount of STORED variables following it): | |
0000 - noop - 0 | |
0100 - clear - 3 | |
0001 - color - 4 | |
0010 - stroke - 1 | |
0011 - line - 4 | |
0101 - rect - 4 | |
0110 - lineRect - 4 | |
0111 - poly - 5 | |
1000 - linePoly - 5 | |
1001 - triangle - 6 | |
1010 - image - 5 | |
---------------- | |
0101 - print | |
inst arg | | |
0101 0000 | 000000 00 | |
Appends a value to the text buffer of this processor. Numeric values are converted to human-readable strings. | |
No local enums. | |
---------------- | |
0110 - drawflush | |
inst arg | | |
0110 0000 | 000000 00 | |
Renders an RGBA image from the draw buffer and submits an overlay to the block specified in the argument. The buffer is then cleared. | |
No local enums. | |
---------------- | |
0111 - printflush | |
inst arg | | |
0111 0000 | 000000 00 | |
Prints the text buffer to the block specified in the argument. The buffer is then cleared. | |
No local enums. | |
---------------- | |
1000 - getlink | |
inst arg0 | arg1 | |
1000 0000 | 000000 00 | 00000000 | |
Gets the arg1th link of the processor, and stores its building in arg0. | |
No local enums. | |
---------------- | |
1001 - control | |
inst m | arg1 | arg2 | arg3 | arg4 | | |
1001 00 00 | 00000000 | 00000000 | 00 000000 | 0000 0000 | 000000 00 | |
Controls the block arg1 with parameters arg2..4. Arguments may be omitted depending on mode. | |
Local enum values (third argument - amount of STORED variables following it): | |
00 - enabled - 2 | |
01 - shoot - 4 | |
10 - shootp - 3 | |
11 - configure - 2 | |
---------------- | |
1010 - radar | |
inst f1 | f2 | f3| s | arg0 | arg1 | arg2 | | |
1010 000 0 | 00 000 000 | 00000000 | 00 000000 | 0000 0000 | 000000 00 | |
The most complex instruction. | |
Finds an unit according to filters f1, f2, f3, ordered either first or last with arg1, sorted by s, searching from arg0's perspective; and stores the unit in arg2. | |
Local enum values: | |
f1..3 | |
000 - any | |
001 - enemy | |
010 - ally | |
011 - player | |
100 - attacker | |
101 - flying | |
110 - boss | |
111 - ground | |
s | |
000 - distance | |
001 - health | |
010 - shield | |
011 - armor | |
100 - maxHealth | |
---------------- | |
1011 - sensor | |
inst arg0 | arg1 | arg2 | | |
1011 0000 | 000000 00 | 00000000 | 00000000 | 00 000000 | |
Returns the value of arg1 and arg2, and stores it in arg0. | |
No local enums. | |
---------------- | |
1100 - jump | |
inst ptr | op | arg0 | arg1 | | |
1100 0000 | 000000 00 | 0 0000000 | 000 00000 | 00000 000 | |
Jumps to ptr if the expression "arg0 op arg1" evaluates to true. | |
ptr has the type uint10 and is a constant inside 0~1023. | |
Local enum values: | |
000 - equal | |
001 - notEqual | |
010 - lessThan | |
011 - lessThanEq | |
100 - greaterThan | |
101 - greaterThanEq | |
110 - always | |
111 - never | |
---------------- | |
1101 - ubind | |
inst arg0 | | |
1101 0000 | 000000 00 | |
Finds an unit of the type arg0, and stores it in @unit. If no unit of that type is found, stores null in @unit. | |
No local enums. | |
---------------- | |
1110 - ucontrol | |
inst actn | arg0 | arg1 | arg2 | arg3 | arg4 | | |
1110 0000 | 00000000 | 00 000000 | 0000 0000 | 000000 00 | 00000000 | 00000000 | 00 000000 | |
Makes @unit perform a certain action with parameters arg0..4. Arguments may be omitted depending on action. | |
Local enum values (third argument - amount of STORED variables following it): | |
0000 - stop - 0 | |
0001 - move - 2 | |
0010 - approach - 3 | |
0011 - boost - 1 | |
0100 - pathfind - 0 | |
0101 - target - 3 | |
0110 - targetp - 2 | |
0111 - itemDrop - 2 | |
1000 - itemTake - 3 | |
1001 - payDrop - 0 | |
1010 - payTake - 1 | |
1011 - mine - 2 | |
1100 - flag - 1 | |
1101 - build - 5 | |
1110 - getBlock - 4 | |
1111 - within - 4 | |
---------------- | |
1111 - ulocate | |
ulocate ore core true @copper outx outy found building | |
inst what | arg0 | arg1 | arg2 | arg3 | arg4 | | |
1111 0000 | 00000000 | 00 000000 | 0000 0000 | 000000 00 | 00000000 | 00000000 | 00 000000 | |
Makes @unit find something. | |
building - Checks whether there's a building that is arg0 an enemy, stores coordinates in arg1 and arg2; stores it in arg4. If there is no such building, sets arg4 to null (?) and sets arg3 to false. Otherwise, sets arg3 to true. | |
ore - Checks whether an ore of the type arg0 exists, writes its data to arg1..3. | |
damaged/spawn - Checks whether a damaged block/drop zone exists, writes its data to arg1..3. | |
Local enum values (third argument - amount of STORED variables following it): | |
0000 - building core | |
0001 - building storage | |
0010 - building generator | |
0011 - building turret | |
0100 - building factory | |
0101 - building repair | |
0110 - building rally | |
0111 - building battery | |
1000 - building resupply | |
1001 - building reactor | |
1010 - building unitModifier | |
1011 - building extinguisher | |
1100 - ore core | |
1101 - spawn core | |
1110 - damaged core | |
-------------------------------- | |
ENUMS | |
000000000 - false | |
000000001 - true | |
000000010 - null | |
000000011 - @this | |
000000100 - @copper | |
000000101 - @lead | |
000000110 - @metaglass | |
000000111 - @graphite | |
000001000 - @sand | |
000001001 - @coal | |
000001010 - @titanium | |
000001011 - @thorium | |
000001100 - @scrap | |
000001101 - @silicon | |
000001110 - @plastanium | |
000001111 - @phase-fabric | |
000010000 - @surge-alloy | |
000010001 - @spore-pod | |
000010010 - @blast-compound | |
000010011 - @pyratite | |
000010100 - @water | |
000010101 - @slag | |
000010110 - @oil | |
000010111 - @cryofluid | |
000011000 - @build1 | |
000011001 - @build2 | |
000011010 - @build3 | |
000011011 - @build4 | |
000011100 - @build5 | |
000011101 - @build6 | |
000011110 - @build7 | |
000011111 - @build8 | |
000100000 - @build9 | |
000100001 - @build10 | |
000100010 - @build11 | |
000100011 - @build12 | |
000100100 - @build13 | |
000100101 - @build14 | |
000100110 - @build15 | |
000100111 - @build16 | |
000101000 - @graphite-press | |
000101001 - @multi-press | |
000101010 - @silicon-smelter | |
000101011 - @silicon-crucible | |
000101100 - @kiln | |
000101101 - @plastanium-compressor | |
000101110 - @phase-weaver | |
000101111 - @alloy-smelter | |
000110000 - @cryofluid-mixer | |
000110001 - @pyratite-mixer | |
000110010 - @blast-mixer | |
000110011 - @melter | |
000110100 - @separator | |
000110101 - @disassembler | |
000110110 - @spore-press | |
000110111 - @pulverizer | |
000111000 - @coal-centrifuge | |
000111001 - @incinerator | |
000111010 - @copper-wall | |
000111011 - @copper-wall-large | |
000111100 - @titanium-wall | |
000111101 - @titanium-wall-large | |
000111110 - @plastanium-wall | |
000111111 - @plastanium-wall-large | |
001000000 - @thorium-wall | |
001000001 - @thorium-wall-large | |
001000010 - @phase-wall | |
001000011 - @phase-wall-large | |
001000100 - @surge-wall | |
001000101 - @surge-wall-large | |
001000110 - @door | |
001000111 - @door-large | |
001001000 - @scrap-wall | |
001001001 - @scrap-wall-large | |
001001010 - @scrap-wall-huge | |
001001011 - @scrap-wall-gigantic | |
001001100 - @thruster | |
001001101 - @mender | |
001001110 - @mend-projector | |
001001111 - @overdrive-projector | |
001010000 - @overdrive-dome | |
001010001 - @force-projector | |
001010010 - @shock-mine | |
001010011 - @conveyor | |
001010100 - @titanium-conveyor | |
001010101 - @plastanium-conveyor | |
001010110 - @armored-conveyor | |
001010111 - @junction | |
001011000 - @bridge-conveyor | |
001011001 - @phase-conveyor | |
001011010 - @sorter | |
001011011 - @inverted-sorter | |
001011100 - @router | |
001011101 - @distributor | |
001011110 - @overflow-gate | |
001011111 - @underflow-gate | |
001100000 - @mass-driver | |
001100001 - @payload-conveyor | |
001100010 - @payload-router | |
001100011 - @mechanical-pump | |
001100100 - @rotary-pump | |
001100101 - @thermal-pump | |
001100110 - @conduit | |
001100111 - @pulse-conduit | |
001101000 - @plated-conduit | |
001101001 - @liquid-router | |
001101010 - @liquid-tank | |
001101011 - @liquid-junction | |
001101100 - @bridge-conduit | |
001101101 - @phase-conduit | |
001101110 - @power-node | |
001101111 - @power-node-large | |
001110000 - @surge-tower | |
001110001 - @diode | |
001110010 - @battery | |
001110011 - @battery-large | |
001110100 - @combustion-generator | |
001110101 - @thermal-generator | |
001110110 - @steam-generator | |
001110111 - @differential-generator | |
001111000 - @rtg-generator | |
001111001 - @solar-panel | |
001111010 - @solar-panel-large | |
001111011 - @thorium-reactor | |
001111100 - @impact-reactor | |
001111101 - @mechanical-drill | |
001111110 - @pneumatic-drill | |
001111111 - @laser-drill | |
010000000 - @blast-drill | |
010000001 - @water-extractor | |
010000010 - @cultivator | |
010000011 - @oil-extractor | |
010000100 - @core-shard | |
010000101 - @core-foundation | |
010000110 - @core-nucleus | |
010000111 - @vault | |
010001000 - @container | |
010001001 - @unloader | |
010001010 - @duo | |
010001011 - @scatter | |
010001100 - @scorch | |
010001101 - @hail | |
010001110 - @wave | |
010001111 - @lancer | |
010010000 - @arc | |
010010001 - @parallax | |
010010010 - @swarmer | |
010010011 - @salvo | |
010010100 - @segment | |
010010101 - @tsunami | |
010010110 - @fuse | |
010010111 - @ripple | |
010011000 - @cyclone | |
010011001 - @foreshadow | |
010011010 - @spectre | |
010011011 - @meltdown | |
010011100 - @command-center | |
010011101 - @ground-factory | |
010011110 - @air-factory | |
010011111 - @naval-factory | |
010100000 - @additive-reconstructor | |
010100001 - @multiplicative-reconstructor | |
010100010 - @exponential-reconstructor | |
010100011 - @tetrative-reconstructor | |
010100100 - @repair-point | |
010100101 - @resupply-point | |
010100110 - @power-source | |
010100111 - @power-void | |
010101000 - @item-source | |
010101001 - @item-void | |
010101010 - @liquid-source | |
010101011 - @liquid-void | |
010101100 - @illuminator | |
010101101 - @legacy-mech-pad | |
010101110 - @legacy-unit-factory | |
010101111 - @legacy-unit-factory-air | |
010110000 - @legacy-unit-factory-ground | |
010110001 - @launch-pad | |
010110010 - @launch-pad-large | |
010110011 - @interplanetary-accelerator | |
010110100 - @message | |
010110101 - @switch | |
010110110 - @micro-processor | |
010110111 - @logic-processor | |
010111000 - @hyper-processor | |
010111001 - @memory-cell | |
010111010 - @memory-bank | |
010111011 - @logic-display | |
010111100 - @large-logic-display | |
010111101 - @block-forge | |
010111110 - @block-loader | |
010111111 - @block-unloader | |
011000000 - @solid | |
011000001 - @air | |
011000010 - @dagger | |
011000011 - @mace | |
011000100 - @fortress | |
011000101 - @scepter | |
011000110 - @reign | |
011000111 - @nova | |
011001000 - @pulsar | |
011001001 - @quasar | |
011001010 - @vela | |
011001011 - @corvus | |
011001100 - @crawler | |
011001101 - @atrax | |
011001110 - @spiroct | |
011001111 - @arkyid | |
011010000 - @toxopid | |
011010001 - @flare | |
011010010 - @horizon | |
011010011 - @zenith | |
011010100 - @antumbra | |
011010101 - @eclipse | |
011010110 - @mono | |
011010111 - @poly | |
011011000 - @mega | |
011011001 - @quad | |
011011010 - @oct | |
011011011 - @risso | |
011011100 - @minke | |
011011101 - @bryde | |
011011110 - @sei | |
011011111 - @omura | |
011100000 - @alpha | |
011100001 - @beta | |
011100010 - @gamma | |
011100011 - @block | |
011100100 - @totalItems | |
011100101 - @firstItem | |
011100110 - @totalLiquids | |
011100111 - @totalPower | |
011101000 - @itemCapacity | |
011101001 - @liquidCapacity | |
011101010 - @powerCapacity | |
011101011 - @powerNetStored | |
011101100 - @powerNetCapacity | |
011101101 - @powerNetIn | |
011101110 - @powerNetOut | |
011101111 - @ammo | |
011110000 - @ammoCapacity | |
011110001 - @health | |
011110010 - @maxHealth | |
011110011 - @heat | |
011110100 - @efficiency | |
011110101 - @rotation | |
011110110 - @x | |
011110111 - @y | |
011111000 - @shootX | |
011111001 - @shootY | |
011111010 - @shooting | |
011111011 - @mineX | |
011111100 - @mineY | |
011111101 - @mining | |
011111110 - @team | |
011111111 - @type | |
100000000 - @flag | |
100000001 - @controlled | |
100000010 - @commanded | |
100000011 - @name | |
100000100 - @config | |
100000101 - @payloadCount | |
100000110 - @payloadType | |
100000111 - @enabled | |
100001000 - @shoot | |
100001001 - @shootp | |
100001010 - @configure | |
100001011 - @mapw | |
100001100 - @maph | |
100001101 - @links | |
100001110 - @ipt | |
100001111 - @thisx | |
100010000 - @thisy | |
100010001 - @counter - 1 | |
100010010 - @time | |
100010011 - @unit - 1 | |
100010100 - @range | |
100010101 - @timescale | |
111111100 - (constant IEEE754 number header) | |
111111101 - (string literal header) | |
111111110 - (constant 64-bit integer header) | |
111111111 - (constant block link header) | |
Documented by BasedUser AKA router | |
This file is in the public domain. You may modify it without permission. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment