# Dictionary List of words defined in arch-specific boot code and core words. # Glossary Stack notation: " -- ". Rightmost is top of stack (TOS). For example, in "a b -- c d", b is TOS before, d is TOS after. "R:" means that the Return Stack is modified. Some words have a variable stack signature, most often in pair with a flag. These are indicated with "?" to tell that the argu- ment might not be there. For example, "-- n? f" means that "n" might or might not be there. Some words consume contents from input and this is indicated by "x", "y" and "..." elements next to the word itself, not in the stack signature. For example, ": x ... ;" means that the word ":" will consume an element "x" (which is usually explained in the description), followed by an arbitrary length of contents, which is ended by ";". Word references (wordref): When we say we have a "word reference", it's a pointer to a word's entry point. That is, making native jump to the address contained in the wordref will execute the word. For example, the address that "' DUP" puts on the stack is a word reference to DUP. See doc/impl for details. "*I*" in description indicates an IMMEDIATE word. "*A*" in description indicates A register usage. # Symbols Across words, different symbols are used in different contexts, but we try to be consistent in their use. Here's their defini- tions: ! - Store @ - Fetch $ - Initialize ^ - Arguments in their opposite order < - Input > - 1. Pointer in a buffer 2. Opposite of "<". ( - Lower boundary ) - Upper boundary ' - Address of * - Word indirection (pointer to word) ? - "Is it ...?" or "do ... if flag" [...] - Indicates immediateness Placement of those symbols is often important. In I/O-related words for example, symbold to the left of the words refer to input and to the right, output. For "?", placement at the right refer to the first form, placement at the left refer to the second form. # System variables See doc/usage for details. These ones have a "'" pair: BLK> Currently selected Block. CURRENT Address of the last word of the dictionary. HERE Addr of next available space in dict IN( Beginning of the input buffer. IN> Current pos in input buffer. These ones are addresses and must be accessed with @ and !: IOERR Nonzero when an IO error occurred in some drivers. NL 1 or 2 chars to spit during NL>, MSB first. If MSB is 0, it's ignored. LN< Routine that feeds lines to the interpreter. Generally RDLN. BLKDTY Whether current block is dirty # Values and aliases TO x n -- Write n to value x. [TO] x n -- *I*. Same as TO. VAL! n a -- Write n to value a. # Entry management '? x -- f Find x it in dict. If found, f=1. Otherwise, f=0. ' x -- w Push addr of word x to w. If not found, aborts. ['] x -- *I* Like "'", but spits the addr as a number literal. If not found, aborts. FIND sa sl -- w? f Find "sa sl" in dict. If found, w=wordref, f=1. Otherwise, f=0. FORGET x -- Rewind the dictionary (both CURRENT and HERE) up to x's previous entry. # Defining words : x ... ; -- Define a new word. ALIAS x y -- Define an alias y with a starting value of x CREATE x -- Create cell named x. Doesn't allocate. CODE x -- Define a new native word. [COMPILE] x -- *I* Compile word x and write it to HERE. IMMEDIATE words are *not* executed. COMPILE x -- *I* Meta compiles: write wordrefs that will compile x when executed. CONSTANT x n -- Create a constant x with value n. CONSTS ... n -- Creates n new constants. See usage.txt. VALUE x n -- Creates cell x that when called pushes its value. VALUES ... n -- Create a serie of n values. See usage.txt DOER -- See doc/primer DOES> -- See doc/primer IMMEDIATE -- Flag the latest defined word as immediate. LITN n -- Write number n as a literal. # Code generation JMPi! n a -- len Write a native jump to n at address a CALLi! n a -- len Write a native call to n at address a i>! n a -- len Write a native push of number n to PS at address a "len" is the length in bytes of the written binary contents. # Flow Note that flow words can only be used in definitions. In the INTERPRET loop, they don't have the desired effect because each word from the input stream is executed immediately. In this context, branching doesn't work. f IF A ELSE B THEN: if f is true, execute A, if false, execute B. ELSE is optional. [IF] .. [THEN]: Meta-IF. Works outside definitions. No [ELSE]. BEGIN .. f UNTIL: if f is false, branch to BEGIN. BEGIN .. AGAIN: Always branch to BEGIN. n >R BEGIN .. NEXT: Loop n times. ( -- *I* Comment. Ignore input until ")" is read. \ -- *I* Line comment. Ignore input until EOL. [ -- *I* Begin interpretative mode. In a definition, execute words instead of compiling them. ] -- End interpretative mode. ABORT -- Resets PS and RS and returns to interpreter. ABORT" ..." -- *I* Compiles a ." followed by a ABORT. EXECUTE a -- Execute wordref at addr a INTERPRET -- Main interpret loop. LEAVE -- In a DO..LOOP, exit at the next LOOP call. QUIT -- Reset RS, return to interpreter prompt. # Parameter Stack DROP a -- DUP a -- a a ?DUP DUP if a is nonzero NIP a b -- b OVER a b -- a b a ROT a b c -- b c a ROT> a b c -- c a b SWAP a b -- b a TUCK a b -- b a b 2DROP a a -- 2DUP a b -- a b a b # Return Stack >R n -- R:n Pops PS and push to RS R> R:n -- n Pops RS and push to PS R@ -- n Copy RS TOS to PS R~ R:n -- Drop RS TOS # Stacks meta .S -- *A* Prints stack information as well as the contents of PS. SCNT -- n Size of PS in bytes RCNT -- n Size of RS in bytes # Memory @ a -- n Set n to value at address a ! n a -- Store n in address a , n -- Write n in HERE and advance it. +! n a -- Increase number at addr a by n. []= a1 a2 u -- f Compare u bytes between a1 and a2. Returns true if equal. [C]? c a u -- i Look for c in the u bytes at addr a. If found, return index i. Otherwise, i=-1. C@ a -- c Set c to byte at address a C@+ a -- a+1 c Fetch c from a and inc a. C! c a -- Store byte c in address a C!+ c a -- a+1 Store byte c in a and inc a. C, b -- Write byte b in HERE and advance it. nC, n -- Parse next n words and write them as bytes. ALLOT n -- Move HERE by n bytes. ALLOT0 n -- *A* ALLOT and fill with zero. FILL a n b -- *A* Fill n bytes at addr a with val b. L, n -- Write n in little-endian regardless of native endianess (L=LSB first) M, n -- Write n in nig-endian regardless of native endianess (M=MSB first) MOVE a1 a2 u -- *A* Copy u bytes from a1 to a2, starting with a1, going up. MOVE, a u -- *A* Copy u bytes from a to HERE. NOTE: on some arches, []= and [C]? don't support u>$ff. We don't use these words with u>$ff in Collapse OS code. If you do so, make sure your arch is OK with it. # A register >A n -- A:n A> A:n -- n A:n R>A R:n -- A:n A>R A:n -- R:n A:n A+ A:n -- A:n+1 A- A:n -- A:n-1 AC@ A:a -- c A:a AC! c A:a -- A:a AC@+ A:a -- c A:a+1 AC!+ c A:a -- A:a+1 # Arithmetic / Bits + a b -- a+b - a b -- a-b -^ a b -- b-a * a b -- a*b / a b -- a/b << n -- n Shift n left by one bit <<8 n -- n Shift n left by 8 bits >> n -- n Shift n right by one bit >>8 n -- n Shift n right by 8 bit L|M n -- lsb msb Split n word in 2 bytes, MSB on TOS 1+ n -- n+1 1- n -- n-1 MOD a b -- a%b /MOD a b -- r q r:remainder q:quotient AND a b -- a&b OR a b -- a|b XOR a b -- a^b LSHIFT n u -- n Shift n left by u bits RSHIFT n u -- n Shift n right by u bits # Logic = n1 n2 -- f Push true if n1 == n2 < n1 n2 -- f Push true if n1 < n2 > n1 n2 -- f Push true if n1 > n2 >= n1 n2 -- f Push true if n1 >= n2 <= n1 n2 -- f Push true if n1 <= n2 0< n -- f Push true if n-as-signed is negative 0>= n -- f Push true if n-as-signed is positive NOT f -- f Push the logical opposite of f. Always 0 or 1. # Strings and lines See doc/usage for the concepts of strings and lines. LIT" ..." -- Read following characters and write to HERE as a string literal. LNLEN a -- n Return length of line at a, the line ending at the last visible char of it. S= sa1 sl1 sa2 sl2 -- f Returns whether string s1 == s2. # I/O . n -- Print n in its decimal form .x n -- Print n's LSB in hex form. Always 2 characters. .X n -- Print n in hex form. Always 4 characters. Numbers are never considered negative. "-1 .X" --> ffff ," ..." -- Write ... to HERE ." ..." -- *I* Compiles string literal ... followed by a call to STYPE. CURWORD -- sa sl Yield the last read word (see WORD). EMIT c -- Spit char c to output stream EMITLN a -- *A* EMIT line at addr a IN< -- c Read one char from buffered input, if end of input is reached, read new line. IN -- Emit newline PARSE sa sl -- n? f *A* Parses string s as a number and push the result in n if it can be parsed, with f=1. Otherwise, push f=0. PC! c a -- Spit c to port a PC@ a -- c Fetch c from port a SPC> -- Emit space character STYPE sa sl -- *A* EMIT all chars of string. WAITW sa sl -- Call WORD until we get the same string as sa sl. WORD -- sa sl Read one word from buffered input and push it. That word is a string (begins with a length byte). WORD! sa sl -- The next WORD call will not read from input and yield this string instead. These ASCII consts are defined: EOT BS CR LF SPC KEY? and EMIT are aliases to (key?) and (emit) (see doc/drivers) KEY is a loop over KEY?. NL> spits CRLF by default, but can be configured to spit an alternate newline char. See impl.txt. # BLK subsystem (see doc/blk) \S -- Interrupts LOAD of current block. BLK( -- a Beginning addr of blk buf. BLK) -- a Ending addr of blk buf. BLK@ n -- *A* Read block n into buffer and make n active. BLK! -- *A* Write currently active block, if dirty. COPY s d -- *A* Copy contents of s block to d block. FLUSH -- Write current block to disk if dirty and inval- idates current block cache. LIST n -- *A* Prints the contents of the block n on screen in the form of 16 lines of 64 columns. LOAD n -- *A* Interprets Forth code from block n LOADR n1 n2 -- *A* Load block range between n1 and n2, inclusive. WIPE -- *A* Empties current block Note: Most BLK words don't actually use the A register them- selves, but we want to allow BLK drivers to make usage of it, so you *should* guard yourself again A changes when using those. # RX/TX subsystem (see doc/rxtx) RX c -- Spit c to TX, blocking until it can do it. TX[ -- Replace EMIT with TX>. ]TX -- Put back the old EMIT handler. # Other BOOT -- Boot back to a fresh system. CRC16 c b -- c Computes byte b into c, a 16-bit CRC with a $1021 polynomial (XMODEM CRC). DUMP n a -- *A* Prints n bytes at addr a in a hexdump format. Prints in chunks of 8 bytes. Doesn't do partial lines. Output is designed to fit in 32 columns. NOOP -- Do nothing. TICKS n -- Wait for approximately n*100 microseconds. Don't use with n=0. # Loaders These words load the related application from blocks: ARCHM Arch-specific loader words and macros ED Block Editor VE Visual Editor ME Memory Editor RSH Remote shell and XMODEM implementation XCOMP Cross-compilation tools # Kernel internals Some words from the kernel are designed to be internal but ended up being used in "userland". Let's document them: _bchk n -- n Checks whether n is a valid 8-bit signed branching offset, that is, in the range -128 to 127. If not, abort with "br ovfl".