From c2dccbdc18ce3acad449988df6f19a506f9e5b11 Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sat, 24 Jan 2015 10:00:45 -0800 Subject: [PATCH] Fix pointer dereferences once and for all (I hope). Simplify memory manager. Homing in on ethernet interface --- src/libsrc/memmgr.pla | 151 ++++++++++++++++--------------------- src/samplesrc/etherip.pla | 75 +++++++++--------- src/samplesrc/uthernet.pla | 112 ++++++++++++++++----------- src/toolsrc/parse.c | 17 ++--- src/toolsrc/sb.pla | 24 ++---- 5 files changed, 185 insertions(+), 194 deletions(-) diff --git a/src/libsrc/memmgr.pla b/src/libsrc/memmgr.pla index f034478..7180f24 100644 --- a/src/libsrc/memmgr.pla +++ b/src/libsrc/memmgr.pla @@ -48,26 +48,24 @@ end struc t_freblk word fresiz word frenxt - word freprv end // // Block size // const MAX_BLK_SIZE = $2010 const MAX_BLK_MASK = $1FFF -const MIN_BLK_SIZE = $08 -const MIN_BLK_MASK = $07 +const MIN_BLK_SIZE = $04 +const MIN_BLK_MASK = $03 // // Block states // -const HMEM_ADDR = $FFF8 -const HMEM_SIZE = $FFF8 +const HMEM_ADDR = $FFFC +const HMEM_SIZE = $FFFC const HMEM_STATE = $07 const HMEM_MOVEABLE = $00 // Many dependencies on this being $00 const HMEM_AVAIL = $01 const HMEM_LOCKED = $02 const HMEM_SWAPPED = $03 -const HMEM_UNINIT = $04 // // Block flags // @@ -214,44 +212,37 @@ end // // Find exact/best free memory match // -def unlink(freblk) +def unlink(freblk, freprv) // // Unlink free block // - if freblk=>freprv - freblk=>freprv=>frenxt = freblk=>frenxt + if freprv + 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) +def unfre(freblk, freprv, size) word shrink if freblk=>fresiz == size // // Unlink free block // - unlink(freblk) + unlink(freblk, freprv) elsif freblk=>fresiz > size // // Shrink free block // shrink = freblk + size - if freblk=>freprv - freblk=>freprv=>frenxt = shrink + if freprv + 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 @@ -268,30 +259,23 @@ def addfre(freblk) // // Insert into list // - freblk=>freprv = srch - freblk=>frenxt = srch=>frenxt - srch=>frenxt=>freprv = freblk - srch=>frenxt = freblk + freblk=>frenxt = srch=>frenxt + srch=>frenxt = freblk return fin - srch = srch=>frenxt + 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 - if frelst - frelst=>freprv = freblk - fin - frelst = freblk + frelst = freblk fin end // @@ -309,9 +293,6 @@ def coallesce // srch=>fresiz = srch=>fresiz + srch=>frenxt=>fresiz srch=>frenxt = srch=>frenxt=>frenxt - if srch=>frenxt - srch=>frenxt=>freprv = srch - fin combined = 1 //putc('C') else @@ -321,7 +302,7 @@ def coallesce return combined end def compact - word page, entry, memblk, moveblk, size, srch + word page, entry, memblk, moveblk, size, srch, prev byte moved moved = 0 @@ -332,13 +313,15 @@ def compact memblk = hpgtbl:[page, entry] size = memblk=>blksiz moveblk = 0 + prev = 0 srch = frelst while srch and srch < memblk if srch=>fresiz >= size - moveblk = unfre(srch, size) + moveblk = unfre(srch, prev, size) //putc('M');putc(' ');puth(moveblk);putc('=');puth(memblk);putln break fin + prev = srch srch = srch=>frenxt loop if moveblk @@ -389,6 +372,9 @@ def swapout(accessed) // Write it out // if write(ref, memblk, size) == size + // + // Zero size in page table flags swapin to read from disk + // hpgtbl:[page, entry] = HMEM_SWAPPED addfre(memblk) swapped = 1 @@ -412,26 +398,30 @@ end // Find a memory block // def findexact(size) - word srch + word srch, prev srch = frelst + prev = 0 while srch if srch=>fresiz == size //putc('E') - return unlink(srch) + return unlink(srch, prev) fin + prev = srch srch = srch=>frenxt loop end def findbest(size) - word srch, shrink + word srch, prev - srch = frelst + prev = 0 + srch = frelst while srch if srch=>fresiz >= size //putc('B') - return unfre(srch, size) + return unfre(srch, prev, size) fin + prev = srch srch = srch=>frenxt loop end @@ -476,41 +466,36 @@ def swapin(hmem) byte ref word memblk, size - memblk = 0 - when hpgtbl:[hmem.lsb, hmem.msb].lsb & HMEM_STATE - is HMEM_SWAPPED - // - // Swap this block back in + size = hpgtbl:[hmem.lsb, hmem.msb] & HMEM_SIZE + if size + // + // This was just uninitialized memory, don't bother reading from file + // + memblk = findblk(size) + else + // + // Swap this block back in + // + swapfile(@filename, hmem) + get_info(@filename, @info) + size = info:2 // Size encoded in aux type + memblk = findblk(size) + if memblk // - swapfile(@filename, hmem) - get_info(@filename, @info) - size = info:2 // size encoded in aux type - memblk = findblk(size) - if memblk - // - // Read it in - // - ref = open(@filename) - if ref - read(ref, memblk, size) - hpgtbl:[hmem.lsb, hmem.msb] = memblk - close(ref) - destroy(@filename) - else - memblk = 0 - fin + // Read it in + // + ref = open(@filename) + if ref + read(ref, memblk, size) + close(ref) + destroy(@filename) fin - //puts(@swapinstr);puts(@filename);putc('@');puth(memblk);putc(':');puth(size);putln - break - is HMEM_UNINIT - // - // Initialize this block - // - memblk = findblk(hpgtbl:[hmem.lsb, hmem.msb] & HMEM_SIZE) - if memblk - hpgtbl:[hmem.lsb, hmem.msb] = memblk - fin - wend + //puts(@swapinstr);puts(@filename);putc('@');puth(memblk);putc(':');puth(size);putln + fin + fin + if memblk + hpgtbl:[hmem.lsb, hmem.msb] = memblk + fin return memblk end // @@ -567,7 +552,6 @@ export def brk(addr) frelst = heapalign frelst=>fresiz = brksiz frelst=>frenxt = 0 - frelst=>freprv = 0 else poolsize = 0 fin @@ -579,20 +563,18 @@ export def brk(addr) brksiz = addr - heapmark brkblk = heapalloc(brksiz) if brkblk - poolsize = poolsize + brksiz // // Add block to end of free list // + poolsize = poolsize + brksiz brkblk=>fresiz = brksiz brkblk=>frenxt = 0 if frelst srch = frelst while srch=>frenxt; srch = srch=>frenxt; loop - srch=>frenxt = brkblk - brkblk=>freprv = srch + srch=>frenxt = brkblk else - frelst = brkblk - brkblk=>freprv = 0 + frelst = brkblk fin coallesce // combine adjacent free space fin @@ -670,11 +652,12 @@ export def hmemNew(size) for entry = 255 downto 0 if hpgtbl:[page, entry].lsb == HMEM_AVAIL // - // Reserve handle as uninitialized memory + // Reserve handle as swapped out block + // Nonzero size will flag swapin to not read from disk // //putc('N');putc(' ');putb(entry);putb(page);putc('@') size = ((size + t_memblk) | MIN_BLK_MASK) + 1 - hpgtbl:[page, entry] = size | HMEM_UNINIT + hpgtbl:[page, entry] = size | HMEM_SWAPPED hnew.lsb = page hnew.msb = entry return hnew @@ -690,7 +673,6 @@ export def hmemLock(hmem) memblk = hpgtbl:[hmem.lsb, hmem.msb] when memblk.lsb & HMEM_STATE - is HMEM_UNINIT is HMEM_SWAPPED memblk = swapin(hmem) if not memblk; return 0; fin @@ -732,7 +714,6 @@ export def hmemRef(hmem) memblk = hpgtbl:[hmem.lsb, hmem.msb] when memblk.lsb & HMEM_STATE - is HMEM_UNINIT is HMEM_SWAPPED memblk = swapin(hmem) is HMEM_LOCKED @@ -768,8 +749,6 @@ export def hmemDel(hmem) memblk->blkref = ref fin break - is HMEM_UNINIT - hpgtbl:[hmem.lsb, hmem.msb] = HMEM_AVAIL wend end // diff --git a/src/samplesrc/etherip.pla b/src/samplesrc/etherip.pla index 2e8279a..5af0965 100644 --- a/src/samplesrc/etherip.pla +++ b/src/samplesrc/etherip.pla @@ -1,27 +1,11 @@ -import STDLIB +import stdlib predef syscall, call, memset, getc, gets, putc, puts, putln predef memset, memcpy, modaddr, modexec predef heapmark, heapallocalign, heapalloc, heaprelease byte MACHID end -// -// Ethernet adapter driver -// -byte etherlib = "UTHERNET", 0 -struc t_edrvr - word fillMAC - word writeFrame - word readFrame - word recvFrame -end -word edrvr -// -// Ethernet packet header -// -struc t_ether - byte[6] hwdst - byte[6] hwsrc - word payload +import uthernet + predef MAC, writeEther, readEther, recvEther end // // IP datagram header @@ -75,10 +59,13 @@ byte[4] localip = 192,168,123,10 byte[6] remoteha byte[4] remoteip = 192,168,123,1 // +// ARP segment list +// +word segARP = @ARP, t_arp +// // Max Ethernet frame size // -const maxesize = 1518 -word pkt, len +const MAX_FRAME_SIZE = 1518 // // Defines for ASM routines // @@ -202,21 +189,37 @@ def dumpfrm(packet, len) next putln end - -if modexec(@etherlib) == 0 - edrvr = modaddr(@etherlib) - 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 +// +// Service incoming packets +// +def serviceIP + word pkt, len + + when recvEther() + is 0 + break + is PAYLOAD_ARP + pkt = heapalloc(MAX_FRAME_SIZE) + len = readEther(pkt, t_arp) dumparp(pkt) - else + readEther(pkt, len) // read remaining packet data + heaprelease(pkt) + break + otherwise + len = readEther(pkt, 0) + pkt = heapalloc(len) + readEther(pkt, len) dumpfrm(pkt, len) - fin - heaprelease(pkt) - fin - ^$C010 -fin + heaprelease(pkt) + wend +end + +localha:0 = MAC:0 +localha:2 = MAC:2 +localha:4 = MAC:4 +writeEther(@BCAST, PAYLOAD_ARP, @segARP, t_arp) +repeat + serviceIP +until ^$C000 > 127 +^$C010 done \ No newline at end of file diff --git a/src/samplesrc/uthernet.pla b/src/samplesrc/uthernet.pla index ad36851..51a24b4 100644 --- a/src/samplesrc/uthernet.pla +++ b/src/samplesrc/uthernet.pla @@ -1,4 +1,4 @@ -import STDLIB +import stdlib predef syscall, call, memset, getc, gets, putc, puts, putln predef memset, memcpy, modaddr, modexec predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail @@ -10,15 +10,6 @@ end const modkeep = $2000 const modinitkeep = $4000 // -// Module interface defined by first 4 fields: -// word fillMAC -// word writeFrame -// word readFrame -// word nextEvent -// -predef fillmac, writefrm, readfrm, recvfrm -word = @fillmac, @writefrm, @readfrm, @recvfrm, 0 -// // Uthernet register offsets // const TXDATA = $00 @@ -41,7 +32,7 @@ byte pregdata // // MAC address // -byte MAC = $00,$0A,$99,$1E,$02,$00 +export byte MAC = $00,$0A,$99,$1E,$02,$00 // // Ethernet header // @@ -51,8 +42,14 @@ struc t_ehdr word ehdr_type end // -// Current status an packet len -word status, len // MUST be in this order! +// Max Ethernet frame size +// +const MAX_FRAME_SIZE = 1518 +// +// Current receive status and packet size +// +word rxstatus, rxsize // MUST be in this order! +word rxpacket, rxptr // // Defines for ASM routines // @@ -94,8 +91,8 @@ asm _peekiowh RTS end // -// POKE PACKET FRAME INTO I/O SPACE -// _pokefrm(BUF, LEN) +// WRITE PACKET FRAME INTO I/O SPACE +// pokefrm(BUF, LEN) // asm pokefrm LDY #$00 @@ -132,8 +129,8 @@ asm _pokefrmh RTS end // -// PEEK PACKET FRAME FROM I/O SPACE -// _peekfrm(BUF, LEN) +// READ PACKET FRAME FROM I/O SPACE +// peekfrm(BUF, LEN) // asm peekfrm LDA ESTKL+1,X @@ -192,13 +189,14 @@ end // // Uthernet interface // -def fillmac(pmac) - pmac=>0 = MAC:0 - pmac=>2 = MAC:2 - pmac=>4 = MAC:4 - return pmac + 6 +export def writeEther(packet, size) + pokeiow(txcmd, $C0) + pokeiow(txlen, size) + repeat; until peekpreg($0138) & $0100 + return pokefrm(packet, size) end -def writefrm(destha, payload, packet, size) +export def writevEther(destha, payload, seglist, size) + word segsize pokeiow(txcmd, $C0) pokeiow(txlen, size + t_ehdr) @@ -206,35 +204,63 @@ def writefrm(destha, payload, packet, size) pokefrm(destha, 6) pokefrm(@MAC, 6) pokefrm(@payload, 2) - return pokefrm(packet, size) + while size > 0 + segsize = seglist=>2 + if segsize > size + segsize = size + fin + pokefrm(seglist=>0, segsize) + size = size - segsize + seglist = seglist + 4 + loop end -def readfrm(packet) - byte[t_ehdr] header - word readlen +export def readEther(size) + word segptr - readlen = len - if status & $0100 - peekfrm(@header, t_ehdr) - peekfrm(packet, len) + if rxsize > 0 + if size > rxsize + size = rxsize + fin + segptr = rxptr + rxptr = rxptr + size + rxsize = rxsize - size + else + segptr = 0 fin - status = 0 - len = 0 - return header:ehdr_type + return segptr end -def recvfrm - if len == 0 +export def readvEther(seglist, size) + word segsize + + while size > 0 + segsize = seglist=>2 + size = size - segsize + if segsize > rxsize + segsize = rxsize + fin + memcpy(seglist=>0, rxptr, segsize) + rxptr = rxptr + segsize + rxsize = rxsize - segsize + seglist = seglist + 4 + loop + return rxsize +end +export def recvEther + if rxsize == 0 if peekiow(isq) & $3F == 4 - peekfrm(@status, 4) - if !(status & $0100) - pokepreg($0102, $0140) // Skip pkt - status = 0 - len = 0 + peekfrm(@rxstatus, 4) + if rxstatus & $0100 + if !rxpacket; rxpacket = heapalloc(MAX_FRAME_SIZE); fin + peekfrm(rxpacket, rxsize) + rxptr = rxpacket else - len = len - t_ehdr + pokepreg($0102, $0140) // Skip pkt + rxstatus = 0 + rxsize = 0 fin fin fin - return len + return rxsize end // // Identify Uthernet card and initialize diff --git a/src/toolsrc/parse.c b/src/toolsrc/parse.c index 7bdc57c..ef951dc 100755 --- a/src/toolsrc/parse.c +++ b/src/toolsrc/parse.c @@ -397,13 +397,19 @@ int parse_value(int rvalue) if (deref) push_op(scantoken, 0); else + { + deref++; type |= BPTR_TYPE; + } break; case WPTR_TOKEN: if (deref) push_op(scantoken, 0); else + { + deref++; type |= WPTR_TYPE; + } break; case AT_TOKEN: deref--; @@ -690,16 +696,7 @@ int parse_value(int rvalue) emit_const(value); else if (type & ADDR_TYPE) { - if (type & PTR_TYPE) - { - if (type & FUNC_TYPE) - emit_call(value, ref_type); - else if (type & LOCAL_TYPE) - (type & BYTE_TYPE) ? emit_llb(value + ref_offset) : emit_llw(value + ref_offset); - else - (type & BYTE_TYPE) ? emit_lab(value, ref_offset, ref_type) : emit_law(value, ref_offset, ref_type); - } - else if (type & LOCAL_TYPE) + if (type & LOCAL_TYPE) emit_localaddr(value + ref_offset); else emit_globaladdr(value, ref_offset, ref_type); diff --git a/src/toolsrc/sb.pla b/src/toolsrc/sb.pla index eb18bf4..c807468 100644 --- a/src/toolsrc/sb.pla +++ b/src/toolsrc/sb.pla @@ -3107,14 +3107,16 @@ def parse_value(rvalue) if deref push_op(token, 0) else - type = type | BPTR_TYPE + deref = deref + 1 + type = type | BPTR_TYPE fin break is WPTR_TKN if deref push_op(token, 0) else - type = type | WPTR_TYPE + deref = deref + 1 + type = type | WPTR_TYPE fin break is AT_TKN @@ -3405,23 +3407,7 @@ def parse_value(rvalue) if type & CONST_TYPE emit_const(value) elsif type & ADDR_TYPE - if type & PTR_TYPE - if type & FUNC_TYPE - emit_call(value) - elsif type & LOCAL_TYPE - if type & BYTE_TYPE - emit_llb(value + ref_offset) - else - emit_llw(value + ref_offset) - fin - else - if type & BYTE_TYPE - emit_lab(value, ref_offset) - else - emit_law(value, ref_offset) - fin - fin - elsif type & LOCAL_TYPE + if type & LOCAL_TYPE emit_localaddr(value + ref_offset) else emit_globaladdr(value, ref_offset)