b2cb56d3c8
FossilOrigin-Name: c0466ee9bdc6ca354aaf2e88f5fb9ab3bfe52b531927830b73722b593f9dee57
203 lines
19 KiB
HTML
203 lines
19 KiB
HTML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml"><head>
|
|
<title>.</title>
|
|
<style type="text/css">
|
|
|
|
* { color: #000; background: #fff; max-width: 700px; }
|
|
tt, pre { background: #dedede; color: #111; font-family: monospace;
|
|
white-space: pre; display: block; width: 100%; }
|
|
.indentedcode { margin-left: 2em; margin-right: 2em; }
|
|
.codeblock {
|
|
background: #dedede; color: #111; font-family: monospace;
|
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
|
padding: 7px;
|
|
display: block;
|
|
}
|
|
|
|
.indentedlist { margin-left: 2em; color: #000; }
|
|
|
|
span { white-space: pre; }
|
|
.text { color: #000; white-space: pre; background: #dedede; }
|
|
.colon { color: #000; background: #dedede; }
|
|
.note { color: #000; background: #dedede; }
|
|
.str { color: #000; text-decoration: underline; background: #dedede; }
|
|
.num { color: #000; background: #dedede; font-weight: bold; font-style: italic; }
|
|
.fnum { color: #000; font-weight: bold; background: #dedede; }
|
|
.ptr { color: #000; font-weight: bold; background: #dedede; }
|
|
.fetch { color: #000; font-style: italic; background: #dedede; }
|
|
.store { color: #000; font-style: italic; background: #dedede; }
|
|
.char { color: #000; background: #dedede; }
|
|
.inst { color: #000; background: #dedede; }
|
|
.defer { color: #000; background: #dedede; }
|
|
.imm { color: #000; font-weight: bold; background: #dedede; }
|
|
.prim { color: #000; font-weight: bolder; background: #dedede; }
|
|
|
|
.tt { white-space: pre; font-family: monospace; background: #dedede; }
|
|
|
|
.h1, .h2, .h3, .h4 { white-space: normal; }
|
|
.h1 { font-size: 125%; }
|
|
.h2 { font-size: 120%; }
|
|
.h3 { font-size: 115%; }
|
|
.h4 { font-size: 110%; }
|
|
.hr { display: block; height: 2px; background: #000000; }
|
|
</style>
|
|
</head><body>
|
|
<p><span class="h1">Internals: Nga Virtual Machine</span>
|
|
<br/><br/>
|
|
<span class="h2">Overview</span>
|
|
<br/><br/>
|
|
At the heart of Retro is a simple MISC (minimal instruction
|
|
set computer) processor for a dual stack architecture.
|
|
<br/><br/>
|
|
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.
|
|
<br/><br/>
|
|
<span class="h2">Instruction Table</span>
|
|
<br/><br/>
|
|
<tt class='indentedcode'> | Stacks |</tt>
|
|
<tt class='indentedcode'>| Opcode | Muri | Full Name | Data | Address |</tt>
|
|
<tt class='indentedcode'>| ------ | ---- | ------------------ | ----- | ------- |</tt>
|
|
<tt class='indentedcode'>| 0 | .. | nop | - | - |</tt>
|
|
<tt class='indentedcode'>| 1 | li | lit | -n | - |</tt>
|
|
<tt class='indentedcode'>| 2 | du | dup | n-nn | - |</tt>
|
|
<tt class='indentedcode'>| 3 | dr | drop | n- | - |</tt>
|
|
<tt class='indentedcode'>| 4 | sw | swap | xy-yx | - |</tt>
|
|
<tt class='indentedcode'>| 5 | pu | push | n- | -n |</tt>
|
|
<tt class='indentedcode'>| 6 | po | pop | -n | n- |</tt>
|
|
<tt class='indentedcode'>| 7 | ju | jump | a- | - |</tt>
|
|
<tt class='indentedcode'>| 8 | ca | call | a- | -A |</tt>
|
|
<tt class='indentedcode'>| 9 | cc | conditional call | af- | -A |</tt>
|
|
<tt class='indentedcode'>| 10 | re | return | - | A- |</tt>
|
|
<tt class='indentedcode'>| 11 | eq | equality | xy-f | - |</tt>
|
|
<tt class='indentedcode'>| 12 | ne | inequality | xy-f | - |</tt>
|
|
<tt class='indentedcode'>| 13 | lt | less than | xy-f | - |</tt>
|
|
<tt class='indentedcode'>| 14 | gt | greater than | xy-f | - |</tt>
|
|
<tt class='indentedcode'>| 15 | fe | fetch | a-n | - |</tt>
|
|
<tt class='indentedcode'>| 16 | st | store | na- | - |</tt>
|
|
<tt class='indentedcode'>| 17 | ad | addition | xy-n | - |</tt>
|
|
<tt class='indentedcode'>| 18 | su | subtraction | xy-n | - |</tt>
|
|
<tt class='indentedcode'>| 19 | mu | multiplication | xy-n | - |</tt>
|
|
<tt class='indentedcode'>| 20 | di | divide & remainder | xy-rq | - |</tt>
|
|
<tt class='indentedcode'>| 21 | an | bitwise and | xy-n | - |</tt>
|
|
<tt class='indentedcode'>| 22 | or | bitwise or | xy-n | - |</tt>
|
|
<tt class='indentedcode'>| 23 | xo | bitwise xor | xy-n | - |</tt>
|
|
<tt class='indentedcode'>| 24 | sh | shift | xy-n | - |</tt>
|
|
<tt class='indentedcode'>| 25 | zr | zero return | n-? | - |</tt>
|
|
<tt class='indentedcode'>| 26 | ha | halt | - | - |</tt>
|
|
<tt class='indentedcode'>| 27 | ie | i/o enumerate | -n | - |</tt>
|
|
<tt class='indentedcode'>| 28 | iq | i/o query | n-xy | - |</tt>
|
|
<tt class='indentedcode'>| 29 | ii | i/o invoke | ...n- | - |</tt>
|
|
<br/><br/>
|
|
<span class="h2">Encoding</span>
|
|
<br/><br/>
|
|
Up to four instructions can be packed into each memory cell.
|
|
<br/><br/>
|
|
As an example,
|
|
<br/><br/>
|
|
<tt class='indentedcode'>Opcode 4 Opcode 3 Opcode 2 Opcode 1</tt>
|
|
<tt class='indentedcode'>00000000:00000000:00000000:00000000</tt>
|
|
<br/><br/>
|
|
If we have a bundle of <span class="tt">duliswst</span>, it would look like:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>st sw li du</tt>
|
|
<tt class='indentedcode'>00010000:00000100:00000001:00000010</tt>
|
|
<br/><br/>
|
|
Each <span class="tt">li</span> should have a value in the following cell(s). These
|
|
values will be pushed to the stack. E.g., <span class="tt">lili....</span> and
|
|
1, 2:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>00000000:00000000:00000001:00000001</tt>
|
|
<tt class='indentedcode'>00000000 00000000 00000000 00000001 (1)</tt>
|
|
<tt class='indentedcode'>00000000 00000000 00000000 00000010 (2)</tt>
|
|
<br/><br/>
|
|
<span class="h2">Shifts</span>
|
|
<br/><br/>
|
|
<span class="tt">sh</span> performs a bitwise arithmetic shift operation.
|
|
<br/><br/>
|
|
This takes two values:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>xy</tt>
|
|
<br/><br/>
|
|
And returns a single one:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>z</tt>
|
|
<br/><br/>
|
|
If y is positive, this shifts <span class="tt">x</span> right by <span class="tt">y</span> bits. If negative,
|
|
it shifts left.
|
|
<br/><br/>
|
|
<span class="h2">Queries: Memory, Stacks</span>
|
|
<br/><br/>
|
|
The <span class="tt">fe</span> instruction allows queries of some data related to
|
|
the Nga VM state. These are returned by reading from negative
|
|
addresses:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>| Address | Returns |</tt>
|
|
<tt class='indentedcode'>| ------- | ---------------------- |</tt>
|
|
<tt class='indentedcode'>| -1 | Data stack depth |</tt>
|
|
<tt class='indentedcode'>| -2 | Address stack depth |</tt>
|
|
<tt class='indentedcode'>| -3 | Maximum Image Size |</tt>
|
|
<tt class='indentedcode'>| -4 | Minimum Integer Value |</tt>
|
|
<tt class='indentedcode'>| -5 | Maximum Integer Value |</tt>
|
|
<br/><br/>
|
|
<span class="h2">I/O Devices</span>
|
|
<br/><br/>
|
|
Nga provides three instructions for interacting with I/O devices.
|
|
These are:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>ie i/o enumerate returns the number of attached devices</tt>
|
|
<tt class='indentedcode'>iq i/o query returns information about a device</tt>
|
|
<tt class='indentedcode'>ii i/o interact invokes an interaction with a device</tt>
|
|
<br/><br/>
|
|
As an example, with an implementation providing an output source,
|
|
a block storage system, and keyboard:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>ie will return `3` since there are three i/o devices</tt>
|
|
<tt class='indentedcode'>0 iq will return 0 0, since the first device is a screen</tt>
|
|
<tt class='indentedcode'> (device class 0, version of 0)</tt>
|
|
<tt class='indentedcode'>1 iq will return 1 3, since the second device is a block</tt>
|
|
<tt class='indentedcode'> storage (class 3), with a version of 1</tt>
|
|
<tt class='indentedcode'>2 iq will return 0 1, since the third device is a keyboard</tt>
|
|
<tt class='indentedcode'> (class 1), with a version of 0</tt>
|
|
<br/><br/>
|
|
In this case, some interactions can be defined:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>: c:put</tt>
|
|
<tt class='indentedcode'>i liiire..</tt>
|
|
<tt class='indentedcode'>d 0</tt>
|
|
<br/><br/>
|
|
<tt class='indentedcode'>: c:get</tt>
|
|
<tt class='indentedcode'>i liiire..</tt>
|
|
<tt class='indentedcode'>d 2</tt>
|
|
<br/><br/>
|
|
Setup the stack, push the device handle to the stack, and then use
|
|
<span class="tt">ii</span> to invoke the interaction.
|
|
<br/><br/>
|
|
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 class of 0.
|
|
<br/><br/>
|
|
All other devices are optional and can be specified in any order.
|
|
<br/><br/>
|
|
The currently supported and reserved device identifiers are:
|
|
<br/><br/>
|
|
<tt class='indentedcode'>| ID | Device Type | Notes |</tt>
|
|
<tt class='indentedcode'>| ---- | ---------------- | -------------------------- |</tt>
|
|
<tt class='indentedcode'>| 0000 | Generic Output | Always present as device 0 |</tt>
|
|
<tt class='indentedcode'>| 0001 | Keyboard | |</tt>
|
|
<tt class='indentedcode'>| 0002 | Floating Point | |</tt>
|
|
<tt class='indentedcode'>| 0003 | Block Storage | Raw, 1024 cell blocks |</tt>
|
|
<tt class='indentedcode'>| 0004 | Filesystem | Unix-style Files |</tt>
|
|
<tt class='indentedcode'>| 0005 | Network: Gopher | Make gopher requests |</tt>
|
|
<tt class='indentedcode'>| 0006 | Network: HTTP | Make HTTP requests |</tt>
|
|
<tt class='indentedcode'>| 0007 | Network: Sockets | |</tt>
|
|
<tt class='indentedcode'>| 0008 | Syscalls: Unix | |</tt>
|
|
<tt class='indentedcode'>| 0009 | Scripting Hooks | |</tt>
|
|
<tt class='indentedcode'>| 0010 | Random Number | |</tt>
|
|
<br/><br/>
|
|
This list may be revised in the future. The only guaranteed
|
|
stable indentifier is 0000 for generic output.
|
|
</p>
|
|
</body></html>
|