#define VVS_STDLIB_HEAP
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@ memset (11000)
@ Description:
-@ This function writes pattern into the memory locations:
-@ startaddr -> startaddr+numbytes
+@ Writes 'pattern' in memory locations 'startaddr' to 'startaddr+count'.
@ Call Stack:
@ pattern
@ startaddr
-@ numbytes <-- TOS
+@ count <-- TOS
@ Return Stack:
@ <empty>
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
NSSVTTSSSN | Mark: 11000 (memset)
+SSSTTN | PUSH 3
+NSTTSSSSSTN | JSR > 1000001 (spewreg)
-@ Prepare the stack for computation.
-@ Addr | Contents
-@ 0 | numbytes
-@ 1 | startaddr
-@ 2 | pattern
-
-SSSSN | PUSH 0 (ptr)
-SNT | SWAP
+@ Store 'pattern' into one memory location on each pass through this loop.
+NSSVSSSTTSSSSSSSSSSSN | Mark: 00011000 00000000
+SSSTN | PUSH 1 (ptr)
+TTT | LOAD
+SSSTSN | PUSH 2 (ptr)
+TTT | LOAD
+TSSS | ADD
+SSSTTN | PUSH 3 (ptr)
+TTT | LOAD
TTS | STORE
+
+@ Decrement and check for loop end condition 'count == 0'.
+SSSTN | PUSH 1 (ptr)
+TTT | LOAD
+SNS | DUP
+NTSSSSTTSSSSSSSSSSTN | BRZ > 00011000 00000001
+SSSTN | PUSH 1
+TSST | SUBTRACT
SSSTN | PUSH 1 (ptr)
SNT | SWAP
TTS | STORE
+NSNSSSTTSSSSSSSSSSSN | JMP > 00011000 00000000
+
+@ Clean up and return
+NSSVSSSTTSSSSSSSSSSTN | Mark: 00011000 00000001
+SNN | DROP
+NTN | RTS
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@ memcpy (11001)
+@ Description:
+@ Copies 'count+1' words from 'source' to 'destination'.
+@ Call Stack:
+@ source
+@ destination
+@ count <-- TOS
+@ Return Stack:
+@ <empty>
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+NSSVTTSSTN | Mark: 11001 (memcpy)
+SSSTTN | PUSH 3
+NSTTSSSSSTN | JSR > 1000001 (spewreg)
+
+@ Copy one word on each pass through this loop.
+NSSVSSSTTSSTSSSSSSSSN | Mark: 00011001 00000000
SSSTSN | PUSH 2 (ptr)
+TTT | LOAD
+SSSTN | PUSH 1 (ptr)
+TTT | LOAD
+TSSS | ADD
+SSSTTN | PUSH 3 (ptr)
+TTT | LOAD
+SSSTN | PUSH 1 (ptr)
+TTT | LOAD
+TSSS | ADD
+TTT | LOAD
+TTS | STORE
+
+@ Decrement and check for loop end conditions.
+SSSTN | PUSH 1 (ptr)
+TTT | LOAD
+SNS | DUP
+NTSSSSTTSSTSSSSSSSTN | BRZ > 00011001 00000001
+SSSTN | PUSH 1
+TSST | SUBTRACT
+SSSTN | PUSH 1 (ptr)
SNT | SWAP
TTS | STORE
+NSNSSSTTSSTSSSSSSSSN | JMP > 00011001 00000000
-@ Store pattern into one memory location on each pass through this loop.
-NSSVSSSTTSSSSSSSSSSSN | Mark: 00011000 00000000
-SSSSN | PUSH 0 (ptr)
+@ Clean up and return
+NSSVSSSTTSSTSSSSSSSTN | Mark: 00011001 00000001
+SNN | DROP
+NTN | RTS
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@ memrand (11010)
+@ Description:
+@ Writes random words into memory locations 'startaddr' to 'startaddr+count'.
+@ Call Stack:
+@ count
+@ startaddr <-- TOS
+@ Return Stack:
+@ <empty>
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#include <math.pvvs>
+NSSVTTSTSN | Mark: 11010 (memrand)
+SSSTN | PUSH 1
+NSTTSSSSSTN | JSR > 1000001 (spewreg)
+
+@ Store random word into one memory location on each pass through this loop.
+NSSVSSSTTSTSSSSSSSSSN | Mark: 00011010 00000000
+SNS | DUP
+SSSTN | PUSH 1 (ptr)
TTT | LOAD
+TSSS | ADD
+NSTTSSSSN | JSR > 10000 (random)
+TTS | STORE
+
+@ Decrement and check loop end conditions
+SNS | DUP
+NTSSSSTTSTSSSSSSSSTN | BRZ > 00011010 00000001
+SSSTN | PUSH 1
+TSST | SUBTRACT
+NSNSSSTTSTSSSSSSSSSN | JMP > 00011010 00000000
+
+@ Clean up and return
+NSSVSSSTTSTSSSSSSSSTN | Mark: 00011010 00000001
+SNN | DROP
+NTN | RTS
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@ memcmp (11011)
+@ Description:
+@ Compares two blocks of memory:
+@ blk1ptr -> blk1ptr+count
+@ -- versus --
+@ blk2ptr -> blk2ptr+count
+@ The return value is zero if the blocks are identical, otherwise non-zero.
+@ Call Stack:
+@ count
+@ blk1ptr
+@ blk2ptr <-- TOS
+@ Return Stack:
+@ retvalue <-- TOS
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+NSSVTTSTTN | Mark: 11011 (memcmp)
+SSSTSN | PUSH 2
+NSTTSSSSSTN | JSR > 1000001 (spewreg)
+
+@ Compare one word on each pass through this loop.
+NSSVSSSTTSTTSSSSSSSSN | Mark: 00011011 00000000
+SNS | DUP
+SNS | DUP
SSSTN | PUSH 1 (ptr)
TTT | LOAD
TSSS | ADD
+TTT | LOAD
+SNT | SWAP
+SSTSN | PUSH 2 (ptr)
+TTT | LOAD
+TSSS | ADD
+TTT | LOAD
+TSST | SUBTRACT
+NTSSSSTTSTTSSSSSSTSN | BRZ > 00011011 00000010 (jump if words match)
+
+@ Return 'match? = false'
+SNN | DROP
+SSSTN | PUSH 1
+NTN | RTS
+
+@ Decrement and loop again if loop is not complete.
+NSSVSSSTTSTTSSSSSSTSN | Mark: 00011011 00000010
+SNS | DUP
+NTSSSSTTSTTSSSSSSSTN | BRZ > 00011011 00000001 (jump if loop is complete)
+SSSTN | PUSH 1
+TSST | SUBTRACT
+NSNSSSTTSTTSSSSSSSSN | JMP > 00011011 00000000
+
+@ Return 'match? = true'
+NSSVSSSTTSTTSSSSSSSTN | Mark: 00011011 00000001
+SNN | DROP
+SSSSN | PUSH 0
+NTN | RTS
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@ memsrch (11100)
+@ Description:
+@ Searches the heap from 'address' to 'address+count'.
+@ If 'pattern' is found, the return value is a pointer to the matching word.
+@ If not found, the return value is a null pointer.
+@ Call Stack:
+@ pattern
+@ count
+@ address <-- TOS
+@ Return Stack:
+@ pointer <-- TOS
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+NSSVTTTSSN | Mark: 11100 (memsrch)
+SSSTTN | PUSH 3
+NSTTSSSSSTN | JSR > 1000001 (spewreg)
+
+@ Compare one word on each pass through this loop.
+NSSVSSSTTTSSSSSSSSSSN | Mark: 00011100 00000000
+SNS | DUP
+SSSTN | PUSH 1 (ptr)
+TTT | LOAD
+TSSS | ADD
+TTT | LOAD
+SSSTTN | PUSH 3 (ptr)
+TTT | LOAD
+TSST | SUBTRACT
+NTSSSSTTTSSSSSSSSSTN | BRZ > 00011100 00000001
+SNS | DUP
SSSTSN | PUSH 2 (ptr)
TTT | LOAD
-TTS | STORE
+TSST | SUBTRACT
+NTSSSSTTTSSSSSSSSTSN | BRZ > 00011100 00000010
+SSSTN | PUSH 1
+TSSS | ADD
+NSNSSSTTTSSSSSSSSSSN | JMP > 00011100 00000000
-@ Decrement and check for loop end condition numbytes == 0.
-SSSSN | PUSH 0 (ptr)
+@ Found a match. Clean up and return.
+NSSVSSSTTTSSSSSSSSSTN | Mark: 00011100 00000001
+SSSTN | PUSH 1 (ptr)
TTT | LOAD
+TSSS | ADD
+NTN | RTS
+
+@ No match found. Clean up and return.
+NSSVSSSTTTSSSSSSSSTSN | Mark: 00011100 00000010
+SNN | DROP
+SSSSN | PUSH 0
+NTN | RTS
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@ slurpreg (1000000)
+@ Description:
+@ Reads 'count' values from heap to stack in complementary order to 'spewreg'.
+@ Call Stack:
+@ count
+@ Return Stack:
+@ heap[count]
+@ ...
+@ heap[2]
+@ heap[1] <-- TOS
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+NSSVTSSSSSSN | Mark: 1000000 (slurpreg)
+
+@ Load one word from heap on each pass.
+NSSVSTSSSSSSSSSSSSSSN | Mark: 01000000 00000000
SNS | DUP
-NTSSSSTTSSSSSSSSSSTN | BRZ > 00011000 00000001
+TTT | LOAD
+SNT | SWAP
+
+@ Check for loop completion.
+@ As a side effect, prepare the next address.
SSSTN | PUSH 1
TSST | SUBTRACT
-SSSSN | PUSH 0 (ptr)
+SNS | DUP
+NTSSTSSSSSSSSSSSSSTN | BRZ > 01000000 00000001
+NSNSTSSSSSSSSSSSSSSN | JMP > 01000000 00000000
+NSSVSTSSSSSSSSSSSSSTN | Mark: 01000000 00000001
+SNN | DROP
+NTN | RTS
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@ spewreg (1000001)
+@ Description:
+@ Writes 'count' values from stack to heap in this order:
+@ TOS -> heap[1]
+@ TOS+1 -> heap[2]
+@ ...
+@ TOS+n -> heap[count]
+@ This function uses heap[15] for temporary storage, thus limiting the total
+@ registers to 14 since heap[0] is reserved. Since this function populates
+@ the registers, encoding the value here seems a natural location to document
+@ the limit. TODO: Should this be turned into a CPP define?
+@ Call Stack:
+@ data-words
+@ ...
+@ data-words
+@ count <-- TOS
+@ Return Stack:
+@ <empty>
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+NSSVTSSSSSTN | Mark: 1000001 (spewreg)
+
+@ Create a counter in heap[15] that doubles as a destination pointer generator.
+SSSTTTTN | PUSH 15 (ptr)
+SSSTN | PUSH 1
+TTS | STORE
+
+@ Store one word to heap on each pass.
+NSSVSTSSSSSTSSSSSSSSN | Mark: 01000001 00000000
+SNT | SWAP
+SSSTTTTN | PUSH 15 (ptr)
+TTT | LOAD
SNT | SWAP
TTS | STORE
-NSNSSSTTSSSSSSSSSSSN | JMP > 00011000 00000000
-@ Clean up and return
-NSSVSSSTTSSSSSSSSSSTN | Mark: 00011000 00000001
+@ Check for loop completion.
+SNS | DUP
+SSSTTTTN | PUSH 15 (ptr)
+TTT | LOAD
+TSST | SUBTRACT
+NTSSTSSSSSTSSSSSSSTN | BRZ > 01000001 00000001
+
+@ Increment heap[15] if continuing.
+SSSTTTTN | PUSH 15 (ptr)
+SNS | DUP
+TTT | LOAD
+SSSTN | PUSH 1
+TSSS | ADD
+TTS | STORE
+NSNSTSSSSSTSSSSSSSSN | JMP > 01000001 00000000
+
+@ Clean up and return.
+NSSVSTSSSSSTSSSSSSSTN | Mark: 01000001 00000001
SNN | DROP
NTN | RTS
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@ slurp (11110)
+@ Description:
+@ Reads values from heap to stack in complementary order to 'spew'.
+@ Call Stack:
+@ address
+@ count <-- TOS
+@ Return Stack:
+@ heap[address+count]
+@ ...
+@ heap[address+1]
+@ heap[address] <-- TOS
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+NSSVTTTTSN | Mark: 11110 (slurp)
+SSSTSN | PUSH 2
+NSTTSSSSSTN | JSR > 1000001 (spewreg)
+
+@ Load one word from heap on each pass.
+NSSVSSSTTTTSSSSSSSSSN | Mark: 00011110 00000000
+SSSTN | PUSH 1 (ptr)
+TTT | LOAD
+SSSTSN | PUSH 2 (ptr)
+TTT | LOAD
+TSSS | ADD
+TTT | LOAD
+
+@ Check for loop completion.
+@ As a side effect, prepare the next address.
+SSSTN | PUSH 1 (ptr)
+SNS | DUP
+TTT | LOAD
+SNS | DUP
+NTSSSSTTTTSSSSSSSSTN | BRZ > 00011110 00000001
+SSSTN | PUSH 1
+TSST | SUBTRACT
+TTS | STORE
+NSNSSSTTTTSSSSSSSSSN | JMP > 00011110 00000000
+NSSVSSSTTTTSSSSSSSSTN | Mark: 00011110 00000001
+SNN | DROP
+SNN | DROP
+NTN | RTS
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+@ Name:
+@ spew (11111)
+@ Description:
+@ Writes values from stack to heap in this order:
+@ TOS -> heap[address]
+@ TOS+1 -> heap[address+1]
+@ ...
+@ TOS+n -> heap[address+count]
+@ Call Stack:
+@ data-words
+@ ...
+@ data-words
+@ address
+@ count <-- TOS
+@ Return Stack:
+@ <empty>
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+NSSVTTTTTN | Mark: 11111 (spew)
+SSSTSN | PUSH 2
+NSTTSSSSSTN | JSR > 1000001 (spewreg)
+
+@ Create a counter in heap[3] that doubles as a dest. pointer offset generator.
+SSSTTN | PUSH 3 (ptr)
+SSSSN | PUSH 0
+TTS | STORE
+
+@ Store one word to heap on each pass.
+NSSVSSSTTTTTSSSSSSSSN | Mark: 00011111 00000000
+SSSTSN | PUSH 2 (ptr)
+TTT | LOAD
+SSSTTN | PUSH 3 (ptr)
+TTT | LOAD
+TSSS | ADD
+SNT | SWAP
+TTS | STORE
+
+@ Check for loop completion.
+SSSTN | PUSH 1 (ptr)
+TTT | LOAD
+SSSTTN | PUSH 3 (ptr)
+TTT | LOAD
+TSST | SUBTRACT
+NTSSSSTTTTTSSSSSSSTN | BRZ > 00011111 00000001
+
+@ Increment heap[3] if continuing.
+SSSTTN | PUSH 3 (ptr)
+SNS | DUP
+TTT | LOAD
+SSSTN | PUSH 1
+TSSS | ADD
+TTS | STORE
+NSNSSSTTTTTSSSSSSSSN | JMP > 00011111 00000000
+
+@ Clean up and return.
+NSSVSSSTTTTTSSSSSSSTN | Mark: 00011111 00000001
+NTN | RTS
+
#endif