-SoftMMU-

Contents:

Introduction
Definitions
API Functions
Future plans
LUnix implementation notes


Introduction

One of the biggest complaints about the C64 is that all the available expansions that are cleaning your bank account aren't utilized by any software. Memory expansions are one of the biggest offenders. Even nowadays, the only programs that really utilize the expanded memory as system RAM are terminal programs and text editors. The goal of SoftMMU is to define an API standard that can be used to access any and all available memory expansions. The first implementation will be written for LUnix NG, and will probably find a home in other multitasking C64 OSes like Andre Fachat's OS/A65.

The following memory expansions are the ones that are currently being implemented in SoftMMU:

6502
A single, directly addressable bank of 64K.
C64 w/256K hack
64K address space made up of 4 bankable windows of 16K each. Total memory pool of 256K.
C128
64K address space made up of 1 non-bankable 1K window, and 1 63K bankable window. Total memory pool of up to 256K.
REU
Byte-based DMA copying between system RAM and an external 16M address space. External RAM is not visible to the CPU.
GeoRAM/BBGRam
Provides 1 bank of 256 bytes into a fixed location ($de00) in system RAM. Total memory pool of up to 4M.
Note: C128 w/1M hack, SuperRAM, and RamLink will be supported in the future, but I have no information about them as of yet. The first version of SoftMMU will only support the above, but once everything's working, adding functionality for these 3 will be easy.

To come up with an interface that can accomodate all of these radically different expansion approaches, a program is given a 256-byte window into the 24-bit address space which it actually allocates. Bytes are accessed out of this window with the LDA (window),Y assembly instruction. The program must tell the API to change the portion of the chunk which the window is mirroring when access to memory outside of the 256-byte window is needed. The actual location of the window must be dynamic, to allow for fast random access to flat memory (6502, SuperRAM) and large banks (C128, C64/256K). This allows the API greater flexibility in deciding how the program should see the requested memory, as well as being able to cache multiple windows in system memory.

The pointer to the window lies in zero page, and for multitasking/protected systems, in the user memory context. This pointer is initialized and updated by the SoftMMU API and should be considered by the program to be read-only. Another 16-bit user-space zero page variable contains the upper 16 bits of the 24-bit address of the window's position within the chunk. Finally, a single byte is reserved for system-specific purposes, most probably being a pointer or offset to further internal structures related to the memory chunk. This byte must never be changed by the program.

;Within zero-page
window .word $0000
page   .word $0000
       .byte $00
Multiple chunks may be allocated, each with their own 5-byte zero page structure. All other variables and bookkeeping is handled by the system.

Definitions

.A/.Y et al
When two 6502-series registers are listed in this manner, it represents a 16-bit value whose low byte is in the first register, and whose high byte is in the second. The specific example ".A/.Y" implies the low byte in the accumulator and the high byte in the Y index register.

Memory Chunk
A region of memory that is virtualized through SoftMMU's 24-bit software addressing mechanism. While each memory chunk has its own 24-bit address space, there may be up to 256 different address spaces, for full 32-bit hardware support. Contents of memory chunks may or may not be contiguous in physical memory, but this is transparent to the user program.

Memory Window
A 256-byte portion of a memory chunk which is currently addressable to the user context of a running task, through a zero-page pointer. This pointer is updated by SoftMMU to reflect requests to change the location of the memory window within the memory chunk.

Page
256 contiguous bytes of directly CPU-addressable memory, where the first byte is located at an address which is evenly divisible by 256.

page
The second 16-bit entry in the SoftMMU user zero-page structure, which corresponds to the requested virtual location of a memory window within the corresponding memory chunk. The location of this value (given that .X is a zero-page pointer to the structure) is $02,X.

window
The first 16-bit entry in the SoftMMU user zero-page structure, which is a pointer to the CPU-addressable location of a memory window. The location of this value (given that .X is a zero-page pointer to the structure) is $00,X.

SoftMMU API Functions

xinfoReport SoftMMU and implementation info.
xallocAllocate a memory chunk.
xreallocResize an existing memory chunk.
xgetsizeGet the size of an existing memory chunk.
xfreeDeallocate a memory chunk.
xpagePage through a memory chunk.


xinfo

Returns information about SoftMMU version, system and implementation information. Fairly useless, because enhancements in future versions should be transparent to the API. However, it only takes 7 bytes of memory to implement.

Inputs

None

Returns

.X = SoftMMU version. Major revision in high nybble, minor revision in low nybble.
.Y = Operating system. 0 = LUnix NG
.A = Current memory configuration:
The lower 4 bits define the base system:

%0000: C64
%0001: C64 w/256K
%0010: C128
%0011: C128 w/1M
%0100: SuperCPU 64
%0101: SuperCPU 128
%0110: reserved
%0111: reserved
%1xxx: reserved for different platform(s)

The rest of the bits define the C64/C128 expansions:

$10: REU
$20: GeoRAM/BBGRam
$40: SuperRAM
$80: RamLink

If bit 3 is set, the upper 4 bits are reserved for other platform-specific expansions.


xalloc

Allocates a memory chunk, and creates a window to that chunk. Memory in the chunk is not initialized. The structure that contains the window pointer and page number must be provided by the user program.

Inputs

.X = location in zero page of the user window structure.
.A/.Y = Number of 256-byte pages to allocate.

Returns

.X = preserved
.A/.Y = undefined

Error: Carry set. The program's memory context is not changed.

Success: Carry clear. window will be allocated to point to the newly allocated window, page is initialized to $0000, and the window will mirror the first page of the memory chunk.

Example
;Zero page variables
  window = $fb
  page = $fd

;Allocate 132 pages (33K) of RAM
  ldx #window
  lda #<132
  ldy #>132
  jsr xalloc

xrealloc

Changes the size of an existing memory chunk. Contents of the chunk (up to the new size) are preserved. If the chunk is made smalled, contents which are contained above the new chunk size are lost. If the chunk is made larger, the newly allocated memory is not initialized.

Inputs

.X = location in zero page of the user window structure.
.A/.Y = Number of 256-byte pages to resize the chunk to.

Returns

.X = preserved
.A/.Y = undefined

Error: Carry set. The memory state of the program is not changed.

Success: Carry clear. window is updated if required, and is refreshed with the according page. An undefined condition occurs if page is outside of the bounds of the new chunk.

Example
;Zero page variables
  window = $fb
  page = $fd

  ldx #window
  ...
  jsr xalloc
  ...

;Resize the chunk to 4096 pages (1M) of RAM
  ldx #window
  lda #<4096
  ldy #>4096
  jsr xrealloc

xgetsize

Queries the allocated size of an existing memory chunk.

Inputs

.X = location in zero page of the user window structure.

Returns

.X = preserved

Error: Carry set.

Success: Carry clear. .A/.Y = Size (in pages) of the memory chunk allocated to the structure pointed to by .X

Example
;Zero page variables
  window = $fb
  page = $fd

  ldx #window
  ...
  jsr xalloc
  ...

;See if our memory chunk is >=128k
  ldx #window
  jsr xgetsize
  cpy #1
  bcs bigchunk

xfree

Deallocates a memory chunk that was previously allocated with xalloc.

Inputs

.X = location in zero page of the user window structure.

Returns

.X = preserved
.A/.Y = undefined

If .X points to an unitialized, already freed, or invalid window structure, xfree merely returns.

Example
;Zero page variables
  window = $fb
  page = $fd

  ldx #window
  ...
  jsr xalloc
  ...

;Deallocate the chunk
  ldx #window
  jsr xfree

xpage

Moves the memory window to a different section of the chunk. The implementation may do this in whatever method suits the environment best. This may include changing the window pointer to point to another location in RAM, copying or banking a page of memory into the page that window points to, or a combination of both.

Inputs

.X = location in zero page of the user window structure.
page = holds the page number to mirror in the window.

Returns

.X/.Y/.A = preserved

If page points to a page outside of the bounds of the memory chunk, a Segmentation Fault fatal error occurs.

Example
;Zero page variables
  window = $fb
  page = $fd

  ldx #window
  ...
  jsr xalloc
  ...

;Page in the first page
  lda #$00
  sta page
  sta page+1
  ldx #window
  jsr xpage
  ...

;Look at the next page
  inc page
  bne +
  inc page+1
+ jsr xpage

Future Plans


LUnix Reference Implementation

The code in here is in work and not yet tested. Read through it and reply to me with any corrections, enhancements, or ideas. Geocities' servers only allow certain file extensions to exist in users' directories, so all files have a .txt extension. :-p

Overview of Implementation (read this first)

Config

Lupo Subroutines Core API Commands Expansion drivers
All pages were generated with a text editor.
All images (except counter art and host ads) are generated, owned and (c) by me.

Home - Files - Scratchpad 1