# Internals: Nga Virtual Machine ## Overview At the heart of RETRO is a simple MISC (minimal instruction set computer) processor for a dual stack architecture. This is a very simple and straightforward system. There are 30 instructions. The memory is a linear array of signed 32 bit values. And there are two stacks: one for data and one for return addresses. ## Instruction Table | Opcode | Muri | Full Name | Data Stack | Address Stack | | ------ | ---- | ------------------ | ---------- | ------------- | | 0 | .. | nop | - | - | | 1 | li | lit | -n | - | | 2 | du | dup | n-nn | - | | 3 | dr | drop | n- | - | | 4 | sw | swap | xy-yx | - | | 5 | pu | push | n- | -n | | 6 | po | pop | -n | n- | | 7 | ju | jump | a- | - | | 8 | ca | call | a- | -A | | 9 | cc | conditional call | af- | -A | | 10 | re | return | - | A- | | 11 | eq | equality | xy-f | - | | 12 | ne | inequality | xy-f | - | | 13 | lt | less than | xy-f | - | | 14 | gt | greater than | xy-f | - | | 15 | fe | fetch | a-n | - | | 16 | st | store | na- | - | | 17 | ad | addition | xy-n | - | | 18 | su | subtraction | xy-n | - | | 19 | mu | multiplication | xy-n | - | | 20 | di | divide & remainder | xy-rq | - | | 21 | an | bitwise and | xy-n | - | | 22 | or | bitwise or | xy-n | - | | 23 | xo | bitwise xor | xy-n | - | | 24 | sh | shift | xy-n | - | | 25 | zr | zero return | n-? | - | | 26 | ha | halt | - | - | | 27 | ie | i/o enumerate | -n | - | | 28 | iq | i/o query | n-xy | - | | 29 | ii | i/o invoke | ...n- | - | ## Encoding Up to four instructions can be packed into each memory cell. As an example, Opcode 4 Opcode 3 Opcode 2 Opcode 1 00000000:00000000:00000000:00000000 If we have a bundle of `duliswst`, it would look like: st sw li du 00010000:00000100:00000001:00000010 Each `li` should have a value in the following cell(s). These values will be pushed to the stack. E.g., `lili....` and 1, 2: 00000000:00000000:00000001:00000001 00000000 00000000 00000000 00000001 (1) 00000000 00000000 00000000 00000010 (2) ## Shifts `sh` performs a bitwise arithmetic shift operation. This takes two values: xy And returns a single one: z If y is positive, this shifts `x` right by `y` bits. If negative, it shifts left. ## Queries: Memory, Stacks The `fe` instruction allows queries of some data related to the Nga VM state. These are returned by reading from negative addresses: | Address | Returns | | ------- | ---------------------- | | -1 | Data stack depth | | -2 | Address stack depth | | -3 | Maximum Image Size | | -4 | Minimum Integer Value | | -5 | Maximum Integer Value | ## I/O Devices Nga provides three instructions for interacting with I/O devices. These are: ie i/o enumerate returns the number of attached devices iq i/o query returns information about a device ii i/o interact invokes an interaction with a device As an example, with an implementation providing an output source, a block storage system, and keyboard: ie will return `3` since there are three i/o devices 0 iq will return 0 0, since the first device is a screen (0) with a version of 0 1 iq will return 1 3, since the second device is a block storage (3), with a version of 1 2 iq will return 0 1, since the third device is a keyboard (1), with a version of 0 In this case, some interactions can be defined: : c:put i liiire.. d 0 : c:get i liiire.. d 2 Setup the stack, push the device ID to the stack, and then use `ii` to invoke the interaction. A RETRO system requires one I/O device (a generic output for a single character). This must be the first device, and must have a device ID of 0. All other devices are optional and can be specified in any order. The currently supported and reserved device identifiers are: | ID | Device Type | Notes | | ---- | ---------------- | -------------------------- | | 0000 | Generic Output | Always present as device 0 | | 0001 | Keyboard | | | 0002 | Floating Point | | | 0003 | Block Storage | Raw, 1024 cell blocks | | 0004 | Filesystem | Unix-style Files | | 0005 | Network: Gopher | Make gopher requests | | 0006 | Network: HTTP | Make HTTP requests | | 0007 | Network: Sockets | | | 0008 | Syscalls: Unix | | | 0009 | Scripting Hooks | | | 0010 | Random Number | | This list may be revised in the future. The only guaranteed stable indentifier is 0000 for generic output.