Acheron VM - Virtual 16-bit CPU for 6502 computers

v0.9.1 2012-07-26

Download

In a nutshell

Goals

Nature of the Beast

Acheron is at its core a VM-building toolkit and internal ABI, keeping instruction creation, documentation, and removal very simple and self-contained.  This distribution includes a default instruction set, forming a complete and working VM implementation.

While in one-off uses Acheron can be customized for maximum benefit, additional standardization of the instruction set would be necessary if used for an embedded OS or user-extensible application.  Standardization can be achieved simply by using the same generated include file when building user VM code.

Acheron is solely implemented as compile-time directives in the ca65 toolchain.  It pushes these features hard, and future versions will require external tools to expand past some of these limits and ease customization even further.  Generating the instruction set documentation is optional, and requires Lisp.  (See Configuring and Building the VM)

License

Acheron VM is licensed under the MIT License.

Commercial Support

Commercial services are available through Grindwork Corporation.  Email david.holz at grindwork.com for inquiries.  We'd also love to hear if you're using Acheron VM successfully on your own, or have ported it to other architectures.


Contents

Generated files


Using the Register Window

A preferably large section of zeropage is dedicated to the register stack (rstack).  The register window, exposing registers r0 through r15, slides along the rstack such that r0 is always at its head.  This allows function parameters to live right in registers, instead of always being copied to and from a parameter stack.

When a function call is made, all registers of the caller are visible to the called function.  (The return address and any other overhead goes onto the CPU stack.) If a few local variables are needed, the register stack can be grown while still retaining access to the lower registers of the caller's window.

Before call

               +----+----+----+---
               | r0 | r1 | r2 | ...
               +----+----+----+---

After call and grow 3

                  ___ Caller's r0
                 /
+----+----+----+----+----+----+---
| r0 | r1 | r2 | r3 | r4 | r5 | ...
+----+----+----+----+----+----+---
  \    \    \   
   \____\____\___ Function's local variables

Return values can be written directly into the caller's registers, and multiple return values in high level languages can be easily supported.  The rets instruction both shrinks the rstack and returns from a subroutine, as functions should normally restore the rstack to the caller's original position when they're done.

When the register stack is grown, the newly exposed registers are uninitialized When it is shrunk, there are no guarantees that the lost registers retain their value when regrown, especially if used in a task switching environment.


Memory Usage

The register stack and process state live in a contiguous section of zeropage.  The state variables are at the top of the segment, and the register stack grows down from there.  A few other bytes of temporary zeropage are also used.  (see Configuring)

The CPU stack holds subroutine return addresses and exception handler frames, accessed through the regular stack pointer.  No other $01xx areas are used.

While running, the VM implementation does use self-modification only within instruction processing, so do not swap tasks directly from interrupts; use the 'native' instruction or the trap functionality to cleanly return to a stable between-instructions state.

To swap out a VM process, replace zeropage from rptr's value to zpTop, and the CPU stack including stack pointer.  Other native registers and flags do not need to be saved, but the decimal flag must remain clear when resuming the VM.


Configuring and Building the VM

NOTE - If you download a .zip version of Acheron VM, the binaries and documentation are already built in their normal place.

The primary development platform for Acheron VM has been Cygwin, which is recommended if you're on Windows.  It has been mildly tested on Linux as well.  ca65 and ld65 should be on the path.  The primary development target for running the VM has been the Commodore 64, which is reflected in the default memory configuration and file names.

acheron.cfg configures the memory layout.  The ZPSTACK, ZPTEMP, and ACHERON memory areas define the locations of all the memory used.  Everything else is for creating the necessary output files.

options.inc holds feature-enabling declarations, the end-of-line marker for generated text files, and the per-platform binary file type for the final output.

acheron.asm pulls in most of the instruction definitions via the .include directive, and contains a number of instruction definitions itself.  Deciding which instructions and files of instructions to include is as easy as adding or removing these.  Note that feature declarations from options.inc might also bear overhead in other parts of the code, so be sure to disable the feature if you're removing its associated instructions, to keep things tidy.

The Makefile contains the output filename, as well as the Lisp to use in building the documentation.  CLISP is used by default.  It's easiest to grab this from your Linux package manager or from Cygwin's setup.  If the Lisp implementation is not found, everything else will still be built.

Running make populates the bin directory with the Acheron VM binary, include file, and instruction set documentation.

The obj directory contains much of the assembler output, including the opdesc file which contains the instruction set in raw s-expression form which is read by Lisp, and a VICE labels file.  Start VICE in the following way to feed the labels into its monitor:

x64 -moncommand obj/labels bin/acheron.prg

Test Build

After building the VM so the include file is present, make test includes the test.asm file in the binary as well, reporting what the entry point of the test code is.  test.asm just launches a small snippet of Acheron code to get you started playing around.