mirror of
https://github.com/dschmenk/PLASMA.git
synced 2025-01-11 13:29:44 +00:00
Adding handle based swapping memory manager
This commit is contained in:
parent
6aebc2ef4f
commit
8ff8a37a68
BIN
DEMO.0.10.PO
BIN
DEMO.0.10.PO
Binary file not shown.
BIN
DEMO.0.9.PO
BIN
DEMO.0.9.PO
Binary file not shown.
775
src/libsrc/memmgr.pla
Normal file
775
src/libsrc/memmgr.pla
Normal file
@ -0,0 +1,775 @@
|
||||
//
|
||||
// Handle based memory manager
|
||||
//
|
||||
import STDLIB
|
||||
predef syscall, call, memset, getc, gets, putc, puts, putln
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease
|
||||
predef isugt, isuge, isult, isule
|
||||
byte MACHID
|
||||
end
|
||||
const iobuffer = $0800
|
||||
struc t_initdata
|
||||
word volptr
|
||||
word freeblks
|
||||
word ramvol
|
||||
word bestvol
|
||||
word ramfree
|
||||
word bestfree
|
||||
word filecnt
|
||||
word catentry
|
||||
byte catref
|
||||
byte firstblk
|
||||
byte entrylen
|
||||
byte entriesblk
|
||||
byte swapstrlen
|
||||
byte[] info
|
||||
byte[] catalog
|
||||
end
|
||||
word initdata
|
||||
//
|
||||
// Access bytes within a word
|
||||
//
|
||||
struc t_word
|
||||
byte lsb
|
||||
byte msb
|
||||
end
|
||||
//
|
||||
// Alloced memory block structure
|
||||
//
|
||||
struc t_memblk
|
||||
byte blksiz
|
||||
byte blkref
|
||||
byte blklok
|
||||
end
|
||||
//
|
||||
// Free memory block structure
|
||||
//
|
||||
struc t_freblk
|
||||
word fresiz
|
||||
word frenxt
|
||||
word freprv
|
||||
end
|
||||
//
|
||||
// Block size
|
||||
//
|
||||
const MAX_BLK_SIZE = $0FE0
|
||||
const MAX_BLK_MASK = $0FF0
|
||||
const MIN_BLK_SIZE = $10
|
||||
const MIN_BLK_MASK = $0F
|
||||
//
|
||||
// Block states
|
||||
//
|
||||
const HMEM_ADDR = $FFFC
|
||||
const HMEM_STATE = $03
|
||||
const HMEM_MOVEABLE = $00 // Many dependencies on this being $00
|
||||
const HMEM_AVAIL = $01
|
||||
const HMEM_LOCKED = $02
|
||||
const HMEM_SWAPPED = $03
|
||||
//
|
||||
// Block flags
|
||||
//
|
||||
const HMEM_ACCESSED = $80
|
||||
//
|
||||
// Handle modifier
|
||||
//
|
||||
const HMOD = $4321
|
||||
//
|
||||
// Handle tables/lists
|
||||
//
|
||||
const PG_SIZE = 512
|
||||
const PG_ENTRIES = 256
|
||||
const PG_TBL_SIZE = 8
|
||||
word[PG_TBL_SIZE] hpgtbl // Handle page table
|
||||
word pooladdr
|
||||
word poolsize
|
||||
word frelst // Free list
|
||||
byte sweeppg, sweepen
|
||||
byte[64] swapvol = "/" // Swap volume
|
||||
byte swapdir = "/SWAP/"
|
||||
byte hexchar = '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
|
||||
//
|
||||
// Fill block filename
|
||||
//
|
||||
def strcharadd(str, char)
|
||||
^str = ^str + 1
|
||||
str->[^str] = char
|
||||
end
|
||||
def swapfile(filestr, hmem)
|
||||
memcpy(filestr, @swapvol, swapvol + 1)
|
||||
strcharadd(filestr, 'H')
|
||||
strcharadd(filestr, hexchar[(hmem >> 12) & $0F])
|
||||
strcharadd(filestr, hexchar[(hmem >> 8) & $0F])
|
||||
strcharadd(filestr, hexchar[(hmem >> 4) & $0F])
|
||||
strcharadd(filestr, hexchar[ hmem & $0F])
|
||||
end
|
||||
def open(path)
|
||||
byte params[6]
|
||||
|
||||
params.0 = 3
|
||||
params:1 = path
|
||||
params:3 = iobuffer
|
||||
params.5 = 0
|
||||
syscall($C8, @params)
|
||||
return params.5
|
||||
end
|
||||
def close(refnum)
|
||||
byte params[2]
|
||||
|
||||
params.0 = 1
|
||||
params.1 = refnum
|
||||
return syscall($CC, @params)
|
||||
end
|
||||
def read(refnum, buff, len)
|
||||
byte params[8]
|
||||
|
||||
params.0 = 4
|
||||
params.1 = refnum
|
||||
params:2 = buff
|
||||
params:4 = len
|
||||
params:6 = 0
|
||||
syscall($CA, @params)
|
||||
return params:6
|
||||
end
|
||||
def write(refnum, buff, len)
|
||||
byte params[8]
|
||||
|
||||
params.0 = 4
|
||||
params.1 = refnum
|
||||
params:2 = buff
|
||||
params:4 = len
|
||||
params:6 = 0
|
||||
syscall($CB, @params)
|
||||
return params:6
|
||||
end
|
||||
def get_eof(refnum)
|
||||
byte params[5]
|
||||
|
||||
params.0 = 2
|
||||
params.1 = refnum
|
||||
params:2 = 0
|
||||
params.4 = 0
|
||||
syscall($D1, @params)
|
||||
return params:2
|
||||
end
|
||||
def get_info(path, infoptr)
|
||||
byte params[18]
|
||||
|
||||
memset(@params, 18, 0)
|
||||
params.0 = 10
|
||||
params:1 = path
|
||||
syscall($C4, @params)
|
||||
return memcpy(infoptr, @params.3, 15)
|
||||
end
|
||||
def create(path, access, type, aux)
|
||||
byte params[12], kind
|
||||
|
||||
kind = $01
|
||||
if type == $0F
|
||||
kind = $0D
|
||||
fin
|
||||
params.0 = 7
|
||||
params:1 = path
|
||||
params.3 = access
|
||||
params.4 = type
|
||||
params:5 = aux
|
||||
params.7 = kind
|
||||
params:8 = 0
|
||||
params:10 = 0
|
||||
return syscall($C0, @params)
|
||||
end
|
||||
def destroy(path)
|
||||
byte params[12]
|
||||
|
||||
params.0 = 1
|
||||
params:1 = path
|
||||
return syscall($C1, @params)
|
||||
end
|
||||
def volumes(unit, buff)
|
||||
byte params[4]
|
||||
|
||||
params.0 = 2
|
||||
params.1 = unit
|
||||
params:2 = buff
|
||||
return syscall($C5, @params)
|
||||
end
|
||||
//
|
||||
// Find exact/best free memory match
|
||||
//
|
||||
def unlink(freblk)
|
||||
//
|
||||
// Unlink free block
|
||||
//
|
||||
if freblk=>freprv
|
||||
freblk=>freprv=>frenxt = freblk=>frenxt
|
||||
else
|
||||
frelst = freblk=>frenxt
|
||||
fin
|
||||
if freblk=>frenxt
|
||||
freblk=>frenxt=>freprv = freblk=>freprv
|
||||
fin
|
||||
return freblk
|
||||
end
|
||||
def unfre(freblk, size)
|
||||
word shrink
|
||||
|
||||
if freblk=>fresiz == size
|
||||
//
|
||||
// Unlink free block
|
||||
//
|
||||
unlink(freblk)
|
||||
elsif freblk=>fresiz > size
|
||||
//
|
||||
// Shrink free block
|
||||
//
|
||||
shrink = freblk + size
|
||||
if freblk=>freprv
|
||||
freblk=>freprv=>frenxt = shrink
|
||||
else
|
||||
frelst = shrink
|
||||
fin
|
||||
if freblk=>frenxt
|
||||
freblk=>frenxt=>freprv = shrink
|
||||
fin
|
||||
shrink=>fresiz = freblk=>fresiz - size
|
||||
shrink=>frenxt = freblk=>frenxt
|
||||
shrink=>freprv = freblk=>freprv
|
||||
else
|
||||
freblk = 0
|
||||
fin
|
||||
return freblk
|
||||
end
|
||||
def addfre(freblk)
|
||||
word srch
|
||||
|
||||
freblk=>fresiz = freblk=>blksiz << 4
|
||||
if frelst and frelst < freblk
|
||||
srch = frelst
|
||||
while srch=>frenxt
|
||||
if srch=>frenxt > freblk
|
||||
//
|
||||
// Insert into list
|
||||
//
|
||||
freblk=>freprv = srch
|
||||
freblk=>frenxt = srch=>frenxt
|
||||
srch=>frenxt=>freprv = freblk
|
||||
srch=>frenxt = freblk
|
||||
fin
|
||||
srch = srch=>frenxt
|
||||
loop
|
||||
//
|
||||
// Add to end of list
|
||||
//
|
||||
freblk=>freprv = srch
|
||||
freblk=>frenxt = 0
|
||||
srch=>frenxt = freblk
|
||||
else
|
||||
//
|
||||
// Add to beginning of list
|
||||
//
|
||||
freblk=>freprv = 0
|
||||
freblk=>frenxt = frelst
|
||||
frelst = freblk
|
||||
fin
|
||||
end
|
||||
def findexact(size)
|
||||
word srch
|
||||
|
||||
srch = frelst
|
||||
while srch
|
||||
if srch=>fresiz == size
|
||||
return unlink(srch)
|
||||
fin
|
||||
srch = srch=>frenxt
|
||||
loop
|
||||
end
|
||||
def findbest(size)
|
||||
word srch, shrink
|
||||
|
||||
srch = frelst
|
||||
while srch
|
||||
if srch=>fresiz >= size
|
||||
return unfre(srch, size)
|
||||
fin
|
||||
srch = srch=>frenxt
|
||||
loop
|
||||
end
|
||||
//
|
||||
// Memory coallesce/compaction/swap out routines
|
||||
//
|
||||
def coallesce
|
||||
word srch, combined
|
||||
|
||||
combined = 0
|
||||
srch = frelst
|
||||
while srch
|
||||
if srch + srch=>fresiz == srch=>frenxt
|
||||
//
|
||||
// Combine adjacent free space
|
||||
//
|
||||
srch=>frenxt = srch=>frenxt=>frenxt
|
||||
if srch=>frenxt
|
||||
srch=>frenxt=>freprv = srch
|
||||
fin
|
||||
combined = 1
|
||||
fin
|
||||
srch = srch=>frenxt
|
||||
loop
|
||||
return combined
|
||||
end
|
||||
def compact
|
||||
word page, entry, memblk, moveblk, size, srch
|
||||
byte moved
|
||||
|
||||
moved = 0
|
||||
for page = PG_TBL_SIZE - 1 downto 0
|
||||
if hpgtbl[page]
|
||||
for entry = 255 downto 0
|
||||
if hpgtbl:[page, entry].lsb & HMEM_STATE == HMEM_MOVEABLE
|
||||
memblk = hpgtbl:[page, entry]
|
||||
size = memblk=>blksiz << 4
|
||||
moveblk = 0
|
||||
srch = frelst
|
||||
while srch and srch < memblk
|
||||
if srch=>fresiz >= size
|
||||
moveblk = unfre(srch)
|
||||
break
|
||||
fin
|
||||
srch = srch=>frenxt
|
||||
loop
|
||||
if moveblk
|
||||
memcpy(moveblk, memblk, size)
|
||||
hpgtbl:[page, entry] = moveblk
|
||||
addfre(memblk)
|
||||
moved = 1
|
||||
fin
|
||||
fin
|
||||
next
|
||||
break
|
||||
fin
|
||||
next
|
||||
if moved
|
||||
coallesce
|
||||
fin
|
||||
return moved
|
||||
end
|
||||
//
|
||||
// Swap out memory block
|
||||
//
|
||||
def swapout(accessed)
|
||||
byte[64] filename
|
||||
byte ref
|
||||
word page, entry, memblk, size, hmem
|
||||
byte swapped
|
||||
|
||||
swapped = 0
|
||||
for page = PG_TBL_SIZE - 1 downto 0
|
||||
if hpgtbl[page]
|
||||
for entry = 255 downto 0
|
||||
if hpgtbl:[page, entry].lsb & HMEM_STATE == HMEM_MOVEABLE
|
||||
memblk = hpgtbl:[page, entry]
|
||||
if not memblk->blklok & accessed
|
||||
//
|
||||
// Swap this block out
|
||||
//
|
||||
size = memblk=>blksiz << 4
|
||||
hmem.lsb = page
|
||||
hmem.msb = entry
|
||||
swapfile(@filename, hmem)
|
||||
create(@filename, $C3, $00, $0000)
|
||||
ref = open(@filename)
|
||||
if ref
|
||||
//
|
||||
// Write it out
|
||||
//
|
||||
if write(ref, memblk, size) == 0
|
||||
hpgtbl:[page, entry] = HMEM_SWAPPED
|
||||
addfre(memblk)
|
||||
swapped = 1
|
||||
fin
|
||||
fin
|
||||
close(ref)
|
||||
fin
|
||||
fin
|
||||
next
|
||||
break
|
||||
fin
|
||||
next
|
||||
if swapped
|
||||
coallesce
|
||||
compact
|
||||
fin
|
||||
return swapped
|
||||
end
|
||||
//
|
||||
// Find a memory block
|
||||
//
|
||||
def getblk(size)
|
||||
word addr
|
||||
|
||||
size = ((size + t_memblk) | MIN_BLK_MASK) + 1
|
||||
if size > MAX_BLK_SIZE; return 0; fin
|
||||
addr = findexact(size)
|
||||
if !addr
|
||||
coallesce
|
||||
addr = findexact(size)
|
||||
if !addr
|
||||
compact
|
||||
addr = findbest(size)
|
||||
if !addr
|
||||
swapout(HMEM_ACCESSED)
|
||||
addr = findbest(size)
|
||||
if !addr
|
||||
swapout(0)
|
||||
addr = findbest(size)
|
||||
fin
|
||||
fin
|
||||
fin
|
||||
fin
|
||||
//
|
||||
// Fill in the block
|
||||
//
|
||||
if addr
|
||||
addr->blksiz = size >> 4
|
||||
addr->blkref = 1
|
||||
addr->blklok = 0
|
||||
fin
|
||||
return addr
|
||||
end
|
||||
//
|
||||
// Swap in a memory block
|
||||
//
|
||||
def swapin(hmem)
|
||||
byte[64] filename
|
||||
byte ref
|
||||
word memblk, size
|
||||
|
||||
memblk = 0
|
||||
if hpgtbl:[hmem.lsb, hmem.msb].lsb == HMEM_SWAPPED
|
||||
//
|
||||
// Swap this block back in
|
||||
//
|
||||
swapfile(@filename, hmem)
|
||||
ref = open(@filename)
|
||||
if ref
|
||||
size = get_eof(ref)
|
||||
memblk = getblk(size - t_memblk - 1)
|
||||
//
|
||||
// Read it in
|
||||
//
|
||||
if memblk
|
||||
hpgtbl:[hmem.lsb, hmem.msb] = memblk
|
||||
read(ref, memblk, size)
|
||||
fin
|
||||
close(ref)
|
||||
destroy(@filename)
|
||||
fin
|
||||
fin
|
||||
return memblk
|
||||
end
|
||||
//
|
||||
// Incrementally clear the ACCESSED BIT
|
||||
//
|
||||
export def sweep
|
||||
word memblk
|
||||
|
||||
if hpgtbl[sweeppg]
|
||||
memblk = hpgtbl:[sweeppg, sweepen]
|
||||
when memblk.lsb & HMEM_STATE
|
||||
is HMEM_MOVEABLE
|
||||
is HMEM_LOCKED
|
||||
memblk = memblk & HMEM_ADDR
|
||||
if memblk->blklok & HMEM_ACCESSED
|
||||
memblk->blklok = memblk->blklok & $7F
|
||||
fin
|
||||
wend
|
||||
if sweepen == 255
|
||||
sweepen = 0
|
||||
if sweeppg == PG_TBL_SIZE - 1
|
||||
sweeppg = 0
|
||||
else
|
||||
sweeppg = sweeppg + 1
|
||||
fin
|
||||
else
|
||||
sweepen = sweepen + 1
|
||||
fin
|
||||
else
|
||||
if sweeppg == PG_TBL_SIZE - 1
|
||||
sweeppg = 0
|
||||
else
|
||||
sweeppg = sweeppg + 1
|
||||
fin
|
||||
fin
|
||||
end
|
||||
//
|
||||
// Set end of memory pool
|
||||
//
|
||||
export def brk(addr)
|
||||
word brksiz, brkblk, srch
|
||||
|
||||
//
|
||||
// Check if addr is too high or low
|
||||
//
|
||||
if isugt(addr, @brksiz); return 0; fin
|
||||
if isule(addr, heapmark); return 0; fin
|
||||
brksiz = 0
|
||||
if not pooladdr
|
||||
//
|
||||
// Allocate the memory pool
|
||||
//
|
||||
brksiz = addr - heapmark
|
||||
if isult(brksiz, MAX_BLK_SIZE); return 0; fin // Not enough heap
|
||||
poolsize = brksiz
|
||||
pooladdr = heapalloc(poolsize)
|
||||
frelst = pooladdr
|
||||
frelst=>fresiz = poolsize
|
||||
frelst=>frenxt = 0
|
||||
frelst=>freprv = 0
|
||||
else
|
||||
//
|
||||
// Can we extend the memory pool?
|
||||
//
|
||||
if pooladdr + poolsize == heapmark
|
||||
brksiz = addr - heapmark
|
||||
if isuge(brksiz, MIN_BLK_SIZE)
|
||||
brkblk = heapalloc(brksiz)
|
||||
//
|
||||
// Add block to end of free list
|
||||
//
|
||||
brkblk=>fresiz = brksiz
|
||||
brkblk=>frenxt = 0
|
||||
if frelst
|
||||
srch = frelst
|
||||
while srch=>frenxt; srch = srch=>frenxt; loop
|
||||
srch=>frenxt = brkblk
|
||||
brkblk=>freprv = srch
|
||||
else
|
||||
frelst = brkblk
|
||||
brkblk=>freprv = 0
|
||||
fin
|
||||
fin
|
||||
fin
|
||||
fin
|
||||
return brksiz
|
||||
end
|
||||
export def sbrk(size)
|
||||
return brk(heapmark + size)
|
||||
end
|
||||
//
|
||||
// Allocate memory block
|
||||
//
|
||||
export def hmemNew(size)
|
||||
word page, entry, hnew, memblk
|
||||
|
||||
//
|
||||
// First, find a free handle
|
||||
//
|
||||
for page = PG_TBL_SIZE - 1 downto 0
|
||||
if !hpgtbl[page]
|
||||
//
|
||||
// Allocate a new page table
|
||||
//
|
||||
hpgtbl[page] = heapalloc(PG_SIZE)
|
||||
memset(hpgtbl[page], PG_SIZE, HMEM_AVAIL)
|
||||
//
|
||||
// Check if we need to allocate the memory pool
|
||||
//
|
||||
if not pooladdr
|
||||
//
|
||||
// Allocate 3/4 of available heap on 128K machine, 1/2 on 64K machine
|
||||
//
|
||||
poolsize = ((@page - heapmark) >> 1) & $7FFF
|
||||
if MACHID & $30 == $30
|
||||
poolsize = poolsize + (poolsize >> 1)
|
||||
fin
|
||||
sbrk(poolsize)
|
||||
fin
|
||||
fin
|
||||
for entry = 255 downto 0
|
||||
if hpgtbl:[page, entry].lsb == HMEM_AVAIL
|
||||
//
|
||||
// Search for the best match
|
||||
//
|
||||
memblk = getblk(size)
|
||||
if !memblk; return 0; fin
|
||||
hpgtbl:[page, entry] = memblk
|
||||
hnew.lsb = page
|
||||
hnew.msb = entry
|
||||
return hnew
|
||||
fin
|
||||
next
|
||||
next
|
||||
end
|
||||
//
|
||||
// Lock memory block in place
|
||||
//
|
||||
export def hmemLock(hmem)
|
||||
word memblk
|
||||
|
||||
memblk = hpgtbl:[hmem.lsb, hmem.msb]
|
||||
when memblk.lsb & HMEM_STATE
|
||||
is HMEM_SWAPPED
|
||||
memblk = swapin(hmem)
|
||||
if not memblk; return 0; fin
|
||||
is HMEM_MOVEABLE
|
||||
hpgtbl:[hmem.lsb, hmem.msb] = memblk | HMEM_LOCKED
|
||||
is HMEM_LOCKED
|
||||
memblk = memblk & HMEM_ADDR
|
||||
memblk->blklok = (memblk->blklok + 1) | HMEM_ACCESSED
|
||||
return memblk + t_memblk
|
||||
wend
|
||||
end
|
||||
//
|
||||
// Unlock memory block
|
||||
//
|
||||
export def hmemUnlock(hmem)
|
||||
byte lock
|
||||
word memblk
|
||||
|
||||
memblk = hpgtbl:[hmem.lsb, hmem.msb]
|
||||
if memblk.lsb & HMEM_STATE == HMEM_LOCKED
|
||||
memblk = memblk & HMEM_ADDR
|
||||
lock = memblk->blklok - 1
|
||||
if lock == HMEM_ACCESSED
|
||||
//
|
||||
// Block is now moveable
|
||||
//
|
||||
hpgtbl:[hmem.lsb, hmem.msb] = memblk
|
||||
fin
|
||||
memblk->blklok = lock
|
||||
fin
|
||||
end
|
||||
//
|
||||
// Increment reference count
|
||||
//
|
||||
export def hmemRef(hmem)
|
||||
word memblk
|
||||
|
||||
memblk = hpgtbl:[hmem.lsb, hmem.msb]
|
||||
when memblk.lsb & HMEM_STATE
|
||||
is HMEM_SWAPPED
|
||||
memblk = swapin(hmem)
|
||||
is HMEM_LOCKED
|
||||
is HMEM_MOVEABLE
|
||||
memblk = memblk & HMEM_ADDR
|
||||
if not memblk; return 0; fin
|
||||
memblk->blkref = memblk->blkref + 1
|
||||
wend
|
||||
end
|
||||
//
|
||||
// Decrement reference count
|
||||
//
|
||||
export def hmemUnref(hmem)
|
||||
byte ref
|
||||
word memblk
|
||||
|
||||
memblk = hpgtbl:[hmem.lsb, hmem.msb]
|
||||
when memblk & HMEM_STATE
|
||||
is HMEM_SWAPPED
|
||||
memblk = swapin(hmem)
|
||||
is HMEM_LOCKED
|
||||
is HMEM_MOVEABLE
|
||||
memblk = memblk & HMEM_ADDR
|
||||
if not memblk; return 0; fin
|
||||
ref = memblk->blkref - 1
|
||||
if ref == 0
|
||||
//
|
||||
// No more references, free block
|
||||
//
|
||||
hpgtbl:[hmem.lsb, hmem.msb] = HMEM_AVAIL
|
||||
addfre(memblk)
|
||||
else
|
||||
memblk->blkref = ref
|
||||
fin
|
||||
wend
|
||||
end
|
||||
//
|
||||
// DEBUG
|
||||
//
|
||||
def putln
|
||||
return putc($0D)
|
||||
end
|
||||
def putb(hexb)
|
||||
return call($FDDA, hexb, 0, 0, 0)
|
||||
end
|
||||
def puth(hex)
|
||||
return call($F941, hex >> 8, hex, 0, 0)
|
||||
end
|
||||
def puti(i)
|
||||
if i < 0; putc('-'); i = -i; fin
|
||||
if i < 10
|
||||
putc(i + '0')
|
||||
else
|
||||
puti(i / 10)
|
||||
putc(i % 10 + '0')
|
||||
fin
|
||||
end
|
||||
//
|
||||
// Search for best swap volume
|
||||
//
|
||||
initdata = heapmark // Use data at top of heap for initialization
|
||||
volumes(0, iobuffer)
|
||||
initdata=>volptr = iobuffer
|
||||
initdata=>ramfree = 0
|
||||
initdata=>bestfree = 0
|
||||
for sweepen = 0 to 15
|
||||
^initdata=>volptr = ^initdata=>volptr & $0F
|
||||
if ^initdata=>volptr
|
||||
memcpy(@swapvol + 2, initdata=>volptr + 1, ^initdata=>volptr)
|
||||
swapvol = ^initdata=>volptr + 1
|
||||
get_info(@swapvol, @initdata->info)
|
||||
initdata=>freeblks = initdata=>info:2 - initdata=>info:5
|
||||
if initdata=>volptr:1 == $522F and initdata=>volptr:3 == $4D41 // '/RAM'
|
||||
if isugt(initdata=>freeblks, initdata=>ramfree)
|
||||
initdata=>ramvol = initdata=>volptr
|
||||
initdata=>ramfree = initdata=>freeblks
|
||||
fin
|
||||
elsif isugt(initdata=>freeblks, initdata=>bestfree)
|
||||
initdata=>bestvol = initdata=>volptr
|
||||
initdata=>bestfree = initdata=>freeblks
|
||||
fin
|
||||
fin
|
||||
initdata=>volptr = initdata=>volptr + 16
|
||||
next
|
||||
if isugt(initdata=>ramfree, $40) or isugt(initdata=>ramfree, initdata=>bestfree) // RAMdrive greater than 64K? Use it
|
||||
initdata=>bestvol = initdata=>ramvol
|
||||
initdata=>bestfree = initdata=>ramfree
|
||||
fin
|
||||
memcpy(@swapvol + 2, initdata=>bestvol + 1, ^initdata=>bestvol)
|
||||
swapvol = ^initdata=>bestvol + 1
|
||||
memcpy(@swapvol + swapvol + 1, @swapdir + 1, swapdir)
|
||||
swapvol = swapvol + swapdir
|
||||
create(@swapvol, $C3, $0F, $0000) // Create the swap directory
|
||||
//
|
||||
// Clear out left over swap files
|
||||
//
|
||||
initdata->catref = open(@swapvol)
|
||||
initdata->firstblk = 1
|
||||
initdata->swapstrlen = swapvol
|
||||
repeat
|
||||
if read(initdata->catref, @initdata->catalog, 512) == 512
|
||||
initdata=>catentry = @initdata->catalog.4
|
||||
if initdata->firstblk
|
||||
initdata->entrylen = initdata->catalog.$23
|
||||
initdata->entriesblk = initdata->catalog.$24
|
||||
initdata=>filecnt = initdata=>catalog:$25
|
||||
initdata=>catentry = initdata=>catentry + initdata->entrylen
|
||||
fin
|
||||
for sweepen = initdata->firstblk to initdata->entriesblk
|
||||
^initdata=>catentry = ^initdata=>catentry & $0F
|
||||
if ^initdata=>catentry
|
||||
memcpy(@swapvol + swapvol + 1, initdata=>catentry + 1, ^initdata=>catentry)
|
||||
swapvol = swapvol + ^initdata=>catentry
|
||||
destroy(@swapvol)
|
||||
swapvol = initdata->swapstrlen
|
||||
fin
|
||||
initdata=>catentry = initdata=>catentry + initdata->entrylen
|
||||
next
|
||||
initdata->firstblk = 0
|
||||
else
|
||||
initdata->filecnt = 0
|
||||
fin
|
||||
until !initdata->filecnt
|
||||
close(initdata->catref)
|
||||
puts(@swapvol); putln
|
||||
done
|
@ -21,6 +21,7 @@ HGR1TEST= HGR1TEST\#FE1000
|
||||
TEST = TEST\#FE1000
|
||||
TESTLIB = TESTLIB\#FE1000
|
||||
PROFILE = PROFILE\#FE1000
|
||||
MEMMGR = MEMMGR\#FE1000
|
||||
PLASM = plasm
|
||||
INCS = toolsrc/tokens.h toolsrc/symbols.h toolsrc/lex.h toolsrc/parse.h toolsrc/codegen.h
|
||||
OBJS = toolsrc/plasm.c toolsrc/parse.o toolsrc/lex.o toolsrc/codegen.o
|
||||
@ -40,7 +41,7 @@ TXTTYPE = .TXT
|
||||
#SYSTYPE = \#FF2000
|
||||
#TXTTYPE = \#040000
|
||||
|
||||
all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(PROFILE) $(ED) $(SB) $(ROD) $(SIEVE) $(UTHERNET) $(ETHERIP) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1)
|
||||
all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(MEMMGR) $(SB) $(ROD) $(SIEVE) $(UTHERNET) $(ETHERIP) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1)
|
||||
|
||||
clean:
|
||||
-rm *FE1000 *FF2000 $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03)
|
||||
@ -97,6 +98,10 @@ $(SB): toolsrc/sb.pla $(PLVM02) $(PLASM) toolsrc/sb.pla
|
||||
./$(PLASM) -A < toolsrc/sb.pla > toolsrc/sb.a
|
||||
acme --setpc 8192 -o $(SB) toolsrc/sb.a
|
||||
|
||||
$(MEMMGR): libsrc/memmgr.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < libsrc/memmgr.pla > libsrc/memmgr.a
|
||||
acme --setpc 4094 -o $(MEMMGR) libsrc/memmgr.a
|
||||
|
||||
$(ROD): samplesrc/rod.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/rod.pla > samplesrc/rod.a
|
||||
acme --setpc 4094 -o $(ROD) samplesrc/rod.a
|
||||
|
@ -1,7 +1,7 @@
|
||||
import STDLIB
|
||||
predef syscall, call, memset, getc, gets, putc, puts, putln
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease
|
||||
byte MACHID
|
||||
end
|
||||
//
|
||||
@ -12,10 +12,18 @@ struc t_edrvr
|
||||
word fillMAC
|
||||
word writeFrame
|
||||
word readFrame
|
||||
word nextEvent
|
||||
word recvFrame
|
||||
end
|
||||
word edrvr
|
||||
//
|
||||
// Ethernet packet header
|
||||
//
|
||||
struc t_ether
|
||||
byte[6] hwdst
|
||||
byte[6] hwsrc
|
||||
word payload
|
||||
end
|
||||
//
|
||||
// IP datagram header
|
||||
//
|
||||
const HW_ETHER = $0100 // BE format
|
||||
@ -48,27 +56,29 @@ struc t_arp
|
||||
byte[6] arp_senderha
|
||||
byte[4] arp_senderip
|
||||
byte[6] arp_targha
|
||||
byte[4] arp_ragip
|
||||
byte[4] arp_targip
|
||||
end
|
||||
byte hARP = $FF,$FF,$FF,$FF,$FF,$FF // BCAST
|
||||
byte MAC = $00,$0A,$99,$1E,$02,$00
|
||||
byte = $08, $06 // ARP payload
|
||||
|
||||
byte pARP = $00, $01 // HW TYPE
|
||||
byte = $08, $00 // PROTO TYPE
|
||||
byte = 6 // HLEN
|
||||
byte = 4 // PLEN
|
||||
byte = $00, $01 // OP
|
||||
byte[6] senderha = $00,$0A,$99,$1E,$02,$00
|
||||
byte[4] senderip = 192,168,123,10
|
||||
byte[6] targha
|
||||
byte[4] targip = 192,168,123,1
|
||||
//
|
||||
// Broadcast address for Ethernet and IP
|
||||
//
|
||||
byte BCAST = $FF, $FF, $FF, $FF, $FF, $FF
|
||||
//
|
||||
// Pre-configured ARP packet
|
||||
//
|
||||
byte ARP = $00, $01 // HW TYPE
|
||||
byte = $08, $00 // PROTO TYPE
|
||||
byte = 6 // HLEN
|
||||
byte = 4 // PLEN
|
||||
byte = $00, $01 // OP
|
||||
byte[6] localha
|
||||
byte[4] localip = 192,168,123,10
|
||||
byte[6] remoteha
|
||||
byte[4] remoteip = 192,168,123,1
|
||||
//
|
||||
// Max Ethernet frame size
|
||||
//
|
||||
const maxesize = 1518
|
||||
const ehdrsize = 14
|
||||
//
|
||||
// Receive packet
|
||||
//
|
||||
byte[maxesize] recvpkt
|
||||
word pkt, len
|
||||
//
|
||||
// Defines for ASM routines
|
||||
//
|
||||
@ -88,10 +98,10 @@ asm swab
|
||||
RTS
|
||||
end
|
||||
//
|
||||
// CHECKSUM BE format
|
||||
// checksum(BUF, LEN)
|
||||
// SUM BE format
|
||||
// sum(BUF, LEN)
|
||||
//
|
||||
asm checksum
|
||||
export asm sum
|
||||
LDY #$00
|
||||
LDA ESTKL+1,X
|
||||
STY ESTKL+1,X
|
||||
@ -126,12 +136,6 @@ CHKLP LDA (SRC),Y
|
||||
DEC ESTKH,X
|
||||
BNE CHKLP
|
||||
INX
|
||||
LDA ESTKL,X
|
||||
EOR #$FF
|
||||
STA ESTKL,X
|
||||
LDA ESTKH,X
|
||||
EOR #$FF
|
||||
STA ESTKH,X
|
||||
RTS
|
||||
end
|
||||
//
|
||||
@ -146,6 +150,41 @@ end
|
||||
def puth(hex)
|
||||
return call($F941, hex >> 8, hex, 0, 0)
|
||||
end
|
||||
def puti(i)
|
||||
if i < 0; putc('-'); i = -i; fin
|
||||
if i < 10
|
||||
putc(i + '0')
|
||||
else
|
||||
puti(i / 10)
|
||||
putc(i % 10 + '0')
|
||||
fin
|
||||
end
|
||||
def putha(haptr)
|
||||
byte i
|
||||
|
||||
for i = 0 to 4
|
||||
putb(haptr->[i]); putc(':')
|
||||
next
|
||||
return putb(haptr->[i])
|
||||
end
|
||||
def putip(ipptr)
|
||||
byte i
|
||||
|
||||
for i = 0 to 2
|
||||
puti(ipptr->[i]); putc('.')
|
||||
next
|
||||
return puti(ipptr->[i])
|
||||
end
|
||||
def dumparp(packet)
|
||||
putha(packet + arp_senderha)
|
||||
putc('=')
|
||||
putip(packet + arp_senderip)
|
||||
putln
|
||||
putha(packet + arp_targha)
|
||||
putc('=')
|
||||
putip(packet + arp_targip)
|
||||
putln
|
||||
end
|
||||
def dumpfrm(packet, len)
|
||||
word i
|
||||
|
||||
@ -161,13 +200,23 @@ def dumpfrm(packet, len)
|
||||
fin
|
||||
putb(^(packet+i))
|
||||
next
|
||||
putln
|
||||
end
|
||||
|
||||
if modexec(@etherlib) == 0
|
||||
edrvr = modaddr(@etherlib)
|
||||
edrvr=>writeFrame(@hARP, @pARP, 28)
|
||||
repeat; until edrvr=>nextEvent() or ^$C000 > 127
|
||||
edrvr=>fillMAC(@localha)
|
||||
edrvr=>writeFrame(@BCAST, PAYLOAD_ARP, @ARP, t_arp)
|
||||
repeat; len = edrvr=>recvFrame(); until len or ^$C000 > 127
|
||||
if len
|
||||
pkt = heapalloc(len)
|
||||
if edrvr=>readFrame(pkt) == PAYLOAD_ARP
|
||||
dumparp(pkt)
|
||||
else
|
||||
dumpfrm(pkt, len)
|
||||
fin
|
||||
heaprelease(pkt)
|
||||
fin
|
||||
^$C010
|
||||
dumpfrm(@recvpkt, edrvr=>readFrame(@recvpkt))
|
||||
fin
|
||||
done
|
@ -16,8 +16,8 @@ const modinitkeep = $4000
|
||||
// word readFrame
|
||||
// word nextEvent
|
||||
//
|
||||
predef fillmac, writefrm, readfrm, nextevt
|
||||
word = @fillmac, @writefrm, @readfrm, @nextevt, 0
|
||||
predef fillmac, writefrm, readfrm, recvfrm
|
||||
word = @fillmac, @writefrm, @readfrm, @recvfrm, 0
|
||||
//
|
||||
// Uthernet register offsets
|
||||
//
|
||||
@ -32,7 +32,7 @@ const AUTO_INC = $8000
|
||||
//
|
||||
// Uthernet register addresses
|
||||
//
|
||||
word slot
|
||||
byte slot[]
|
||||
byte txcmd
|
||||
byte txlen
|
||||
byte isq
|
||||
@ -41,7 +41,7 @@ byte pregdata
|
||||
//
|
||||
// MAC address
|
||||
//
|
||||
byte MAC = $00,$0A,$99,$1E,$02,$00
|
||||
byte MAC = $00,$0A,$99,$1E,$02,$00
|
||||
//
|
||||
// Ethernet header
|
||||
//
|
||||
@ -51,6 +51,9 @@ struc t_ehdr
|
||||
word ehdr_type
|
||||
end
|
||||
//
|
||||
// Current status an packet len
|
||||
word status, len // MUST be in this order!
|
||||
//
|
||||
// Defines for ASM routines
|
||||
//
|
||||
asm equates
|
||||
@ -195,36 +198,51 @@ def fillmac(pmac)
|
||||
pmac=>4 = MAC:4
|
||||
return pmac + 6
|
||||
end
|
||||
def writefrm(header, payload, size)
|
||||
def writefrm(destha, payload, packet, size)
|
||||
|
||||
pokeiow(txcmd, $C0)
|
||||
pokeiow(txlen, size + t_ehdr)
|
||||
repeat; until peekpreg($0138) & $0100
|
||||
pokefrm(header, t_ehdr)
|
||||
pokefrm(payload, size)
|
||||
pokefrm(destha, 6)
|
||||
pokefrm(@MAC, 6)
|
||||
pokefrm(@payload, 2)
|
||||
return pokefrm(packet, size)
|
||||
end
|
||||
def readfrm(packet)
|
||||
word status, len
|
||||
|
||||
peekfrm(@status, 4)
|
||||
byte[t_ehdr] header
|
||||
word readlen
|
||||
|
||||
readlen = len
|
||||
if status & $0100
|
||||
peekfrm(@header, t_ehdr)
|
||||
peekfrm(packet, len)
|
||||
else
|
||||
pokepreg($0102, $0140) // Skip pkt
|
||||
len = 0
|
||||
fin
|
||||
status = 0
|
||||
len = 0
|
||||
return header:ehdr_type
|
||||
end
|
||||
def recvfrm
|
||||
if len == 0
|
||||
if peekiow(isq) & $3F == 4
|
||||
peekfrm(@status, 4)
|
||||
if !(status & $0100)
|
||||
pokepreg($0102, $0140) // Skip pkt
|
||||
status = 0
|
||||
len = 0
|
||||
else
|
||||
len = len - t_ehdr
|
||||
fin
|
||||
fin
|
||||
fin
|
||||
return len
|
||||
end
|
||||
def nextevt
|
||||
return peekiow(isq) & $3F
|
||||
end
|
||||
//
|
||||
// Identify Uthernet card and initialize
|
||||
//
|
||||
for slot = $90 to $F0 step $10
|
||||
for slot = $F0 downto $90 step $10
|
||||
if (peekiow(slot+TXCMD) & $CC3F) == $09
|
||||
pokeiow(slot+PREG_INDEX, 0)
|
||||
if peekiow(slot+PREG_DATA) == $630E
|
||||
txcmd = slot + TXCMD
|
||||
if peekiow(slot+PREG_DATA) == $630E
|
||||
txlen = slot + TXLEN
|
||||
isq = slot + INT_STATUS
|
||||
pregidx = slot + PREG_INDEX
|
||||
@ -234,6 +252,7 @@ for slot = $90 to $F0 step $10
|
||||
_pokefrmh.1 = slot+1
|
||||
_peekfrml.1 = slot
|
||||
_peekfrmh.1 = slot+1
|
||||
txcmd = slot + TXCMD // Set this last
|
||||
pokepreg($0158, MAC:0) // MAC addr
|
||||
pokepreg($015A, MAC:2) // MAC addr
|
||||
pokepreg($015C, MAC:4) // MAC addr
|
||||
|
@ -494,6 +494,12 @@ int parse_value(int rvalue)
|
||||
*/
|
||||
if (emit_value)
|
||||
{
|
||||
if (ref_offset != 0)
|
||||
{
|
||||
emit_const(ref_offset);
|
||||
emit_op(ADD_TOKEN);
|
||||
ref_offset = 0;
|
||||
}
|
||||
if (ref_type & PTR_TYPE)
|
||||
(ref_type & BPTR_TYPE) ? emit_lb() : emit_lw();
|
||||
if (scan_lookahead() != CLOSE_PAREN_TOKEN)
|
||||
@ -559,6 +565,15 @@ int parse_value(int rvalue)
|
||||
}
|
||||
emit_value = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ref_offset != 0)
|
||||
{
|
||||
emit_const(ref_offset);
|
||||
emit_op(ADD_TOKEN);
|
||||
ref_offset = 0;
|
||||
}
|
||||
}
|
||||
while (parse_expr())
|
||||
{
|
||||
if (scantoken != COMMA_TOKEN)
|
||||
@ -600,16 +615,20 @@ int parse_value(int rvalue)
|
||||
}
|
||||
emit_value = 1;
|
||||
}
|
||||
ref_type = (scantoken == PTRB_TOKEN) ? BPTR_TYPE : WPTR_TYPE;
|
||||
ref_offset = 0;
|
||||
if (!parse_const(&ref_offset))
|
||||
scan_rewind(tokenstr);
|
||||
if (ref_offset != 0)
|
||||
else
|
||||
{
|
||||
emit_const(ref_offset);
|
||||
emit_op(ADD_TOKEN);
|
||||
if (ref_offset != 0)
|
||||
{
|
||||
emit_const(ref_offset);
|
||||
emit_op(ADD_TOKEN);
|
||||
}
|
||||
if (ref_type & PTR_TYPE)
|
||||
(ref_type & BPTR_TYPE) ? emit_lb() : emit_lw();
|
||||
}
|
||||
ref_offset = 0;
|
||||
ref_type = (scantoken == PTRB_TOKEN) ? BPTR_TYPE : WPTR_TYPE;
|
||||
if (!parse_const(&ref_offset))
|
||||
scan_rewind(tokenstr);
|
||||
break;
|
||||
case DOT_TOKEN:
|
||||
case COLON_TOKEN:
|
||||
@ -637,21 +656,18 @@ int parse_value(int rvalue)
|
||||
emit_value = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ref_offset != 0)
|
||||
{
|
||||
emit_const(ref_offset);
|
||||
emit_op(ADD_TOKEN);
|
||||
ref_offset = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (emit_value)
|
||||
{
|
||||
if (rvalue && deref && (ref_type & PTR_TYPE))
|
||||
if (ref_offset != 0)
|
||||
{
|
||||
emit_const(ref_offset);
|
||||
emit_op(ADD_TOKEN);
|
||||
ref_offset = 0;
|
||||
}
|
||||
if (deref && (ref_type & PTR_TYPE))
|
||||
(ref_type & BPTR_TYPE) ? emit_lb() : emit_lw();
|
||||
}
|
||||
else
|
||||
@ -692,6 +708,8 @@ int parse_value(int rvalue)
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
if (type & PTR_TYPE)
|
||||
ref_type = type;
|
||||
return (ref_type ? ref_type : WORD_TYPE);
|
||||
}
|
||||
int parse_expr()
|
||||
|
Loading…
x
Reference in New Issue
Block a user