ops that have one variant that takes an immediate in the B position
and another variant (with a different opcode) that takes a local.
-Operand types can be:
-- immediate Byte (incl. signed offset for must jump operations)
-- immediate Word (offset for the "long jumps"--JUMP/EMP?/FALSE?)
-- index into the current function's Constants table
-- index into the current function's Locals table
-- index into the Locals table containing an LVAR to be dereferenced
-Generally each opcode has a fixed interpretation of each operand; any
-necessary variants are encoded as separate opcodes rather than
+The address modes are:
+- B: immediate Byte (incl. signed offset for most jump operations)
+- H: immediate Halfword (16-bit operand, incl long jumps JUMP/EMP?/FALSE?)
+- W: IP-relative Word (32 bit constant inlined in code)
+- L: index into the current function's Locals table
+- LL: index into the Locals table, result indirected through a locative
+The RVECTOR is placed at local0, so that static values can be accessed
+via NTHR and locals with static names via NTHRL.
+
+An opcode interprets each of its arguments according to a fixed
+address mode; any necessary variants are encoded as separate opcodes
+(distinguished in assembly by the suffixes listed above) rather than
branching on flag bits. The only common non-guard branches are the
opcode dispatch, (occasionally prefixed-opcode dispatch), and dispatch
for polymorphic/mistyped ops.
bit63
v
.-------------------------------.
-| end-ptr |
+| cur-ptr |
+-------------------------------+
| length | Typ | Prim |
'-------------------------------'
and run in an internal PROCESS, though some fundamental ops need to be
compiled for a particular type of GC implementation (because hooks for
allocation and read/write barriers need to be as fast as possible).
+
+# Loading MIM Libraries
+
+Usually a whole library (like the stdlib) is statically linked into
+one file, but per-file dynamic linking is also possible.
+
+Run some code from the file, typically a standard loader in the
+header--the loading process is up to the MIM code.
+
+Standard loader needs to, at minimum:
+- lookup some ATOMs from const STRINGs
+- SETG those ATOMs (to LAZY.UBLOCK stub objects or upfront-loaded RVECTORs)
+
+On a MSUBR's first call (or earlier), it's necessary to:
+- create its RVECTOR, including its CODE object
+
+File will look like:
+[ module loader CODE ] (not needed after load)
+[ STRINGs for ATOMs defined on load ] (not needed after load)
+[ RVECTOR loaders... ] (const, each needed once)
+[ MSUBR CODE... ] (rw, persistent)
+
+--if we use the CODE in-place (as mmap'd), the GC can ignore it completely
+RVECTOR loaders:
+- all at once?
+ - much more efficient if we're going to be running them all anyway
+ - section becomes droppable
+ - simpler
+- lazily?
+ - work scales with functions called, not functions available
+ - have to mmap in low-space to make the CODE directly accessible
+- it's up to the loader; initial impl will be upfront
+
+MSUBR calls in a MSUBR can be:
+- unlinked: ATOM in RVECTOR, NTHRGL to look up current value each call
+- linked: MSUBR in RVECTOR, set up by loader
+
+# Licensing
+
+You can redistribute and/or modify this file under the terms of the
+GNU Affero General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any
+later version.
+
+This file is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public
+License along with this file. If not, see
+<http://www.gnu.org/licenses/>.