Cortex code definitions

The file Cortex/CodeCortex.fth contains primitives for the standalone Forth kernel built for Cortex-M3/M4 CPUs. See Cortex/CodeM0M1.fth for Cortex-M0/M1 CPUs.

Notes

Some words and code routines are marked in the documentation as INTERNAL. These are factors used by other words and do not have dictionary entries in the standalone Forth. They are only accessible to users of the VFX Forth ARM Cross Compiler. This also applies to definitions of the form:

n EQU <name>
PROC <name>
L: <name>

Register usage

Note that the use of R8 will change sometime in 2016 to become the floating point stack pointer.

For Cortex-M3/M4 the following register usage is the default:


  r15         pc      program counter
  r14         link    link register; bit0=1=Thumb, usually set
  r13         rsp     return stack pointer
  r12         psp     data stack pointer
  r11         up      user area pointer
  r10         --
  r9          lp      locals pointer
  r8          fsp     will be float stack pointer
  r7          tos     cached top of stack
  r0-r6       scratch

The VFX optimiser uses R0 and R1 for internal operations - you can make no assumptions about their contents on entry to a word. CODE definitions must use R7 as TOS with NOS pointed to by R12 as a full descending stack in ARM terminology. R0..R8 are free for use by CODE definitions and need not be preserved or restored. You should assume that any register can be affected by other words.

For Cortex-M0/M1 code generation, the parameter stack pointer is moved from R12 to R6.


  r15         pc      program counter
  r14         link    link register
  r13         rsp     return stack pointer
  r12         --
  r11         up      user area pointer
  r10         --      RFU
  r9          lp      locals pointer
  r8          fsp     will be float stack pointer
  r7          tos     cached top of stack
  r6          psp     data stack pointer
  r0-r5       scratch

It is implicit throughout the code that the system registers UP, PSP, FSP, RSP are always set so that:

  UP > PSP > FSP > RSP

Because of this layout, data stack underflows may corrupt the first part of the USER area. You have been warned. During testing, it may be as well to set the equate SP-GUARD to 2 or 3 in your control file to leave a few guard cells on the data stack.

Configuration

These equates are set false (zero) if they have not already been defined.

false equ DSQRT?        \ -- flag
Set this non-zero to compile DSQRT.

false equ FastCmove?    \ -- flag
Set this flag true to use a fast but vast (~1kb) version of CMOVE. If your application uses either CMOVE or MOVE in time-critical code, the fast version offers an overall speed up of about four times. The code for the fast but vast version was written by Rowley Associates, whose permission to adapt and publish the code with the MPE cross compiler is much appreciated.

Logical and relational operators

: AND           \ x1 x2 -- x3
Perform a logical AND between the top two stack items and retain the result in top of stack.

: OR            \ x1 x2 -- x3
Perform a logical OR between the top two stack items and retain the result in top of stack.

: XOR           \ x1 x2 -- x3
Perform a logical XOR between the top two stack items and retain the result in top of stack.

: INVERT        \ x -- x'
Perform a bitwise inversion.

: 0=            \ x -- flag
Compare the top stack item with 0 and return TRUE if equals.

: 0<>           \ x -- flag
Compare the top stack item with 0 and return TRUE if not-equal.

: 0<            \ x -- flag
Return TRUE if the top of stack is less-than-zero.

: 0>            \ x -- flag
Return TRUE if the top of stack is greater-than-zero.

: =             \ x1 x2 -- flag
Return TRUE if the two topmost stack items are equal.

: <>            \ x1 x2 -- flag
Return TRUE if the two topmost stack items are different.

: <             \ n1 n2 -- flag
Return TRUE if n1 is less than n2.

: >             \ n1 n2 -- flag
Return TRUE if n1 is greater than n2.

: <=            \ n1 n2 -- flag
Return TRUE if n1 is less than or equal to n2.

: >=            \ x1 x2 -- flag
Return TRUE if n1 is greater than or equal to n2.

: U>            \ u2 u2 -- flag
An UNSIGNED version of >.

: U<            \ u1 u2 -- flag
An UNSIGNED version of <.

CODE DU<        \ ud1 ud2 -- flag
Returns true if ud1 (unsigned double) is less than ud2.

: D0<           \ d -- flag
Returns true if signed double d is less than zero.

: D0=   \ xd -- flag
Returns true if xd is 0.

CODE D=         \ xd1 xd2 -- flag
Return TRUE if the two double numbers are equal.

CODE D<         \ d1 d2 -- flag
Return TRUE if the double number d1 is (signed) less than the double number d2.

CODE DMAX       \ d1 d2 -- d3 ; d3=max of d1/d2
Return the maximum double number from the two supplied.

CODE DMIN       \ d1 d2 -- d3 ; d3=min of d1/d2
Return the minimum double number from the two supplied.

CODE MIN        \ n1 n2 -- n1|n2
Given two data stack items preserve only the smaller.

CODE MAX        \ n1 n2 -- n1|n2
Given two data stack items preserve only the larger.

CODE WITHIN?    \ n1 n2 n3 -- flag
Return TRUE if N1 is within the range N2..N3. This word uses signed arithmetic.

CODE WITHIN     \ n1|u1 n2|u2 n3|u3 -- flag
The ANS version of WITHIN?. This word uses unsigned arithmetic, so that signed compares are treated as existing on a number circle.

CODE LSHIFT     \ x1 u -- x2
Logically shift X1 by U bits left.

CODE RSHIFT     \ x1 u -- x2
Logically shift X1 by U bits right.

Control flow

CODE EXECUTE    \ xt --
Execute the code described by the XT. This is a Forth equivalent to an assembler JSR/CALL instruction.

CODE BRANCH     \ --
The run time action of unconditional branches compiled on the target. INTERNAL.

CODE ?BRANCH    \ n --
The run time action of conditional branches compiled on the target. INTERNAL.

CODE (OF)       \ n1 n2 -- n1|--
The run time action of OF compiled on the target. INTERNAL.

CODE (LOOP)     \ --
The run time action of LOOP compiled on the target. INTERNAL.

CODE (+LOOP)    \ n --
The run time action of +LOOP compiled on the target. INTERNAL.

CODE (DO)       \ limit index --
The run time action of DO compiled on the target. INTERNAL.

CODE (?DO)      \ limit index --
The run time action of ?DO compiled on the target. INTERNAL.

CODE LEAVE      \ --
Remove the current DO..LOOP parameters and jump to the end of the DO..LOOP structure.

CODE ?LEAVE     \ flag --
If flag is non-zero, remove the current DO..LOOP parameters and jump to the end of the DO..LOOP structure.

CODE I          \ -- n
Return the current index of the inner-most DO..LOOP.

CODE J          \ -- n
Return the current index of the second DO..LOOP.

CODE UNLOOP     \ -- ; R: loop-sys --
Remove the DO..LOOP control parameters from the return stack.

Basic arithmetic

CODE S>D        \ n -- d
Convert a single number to a double one.

: D>S           \ d -- n
Convert a double number to a single.

: NOOP  ;       \ --
A NOOP, null instruction.

CODE M+     \ d1|ud1 n -- d2|ud2
Add double d1 to sign extended single n to form double d2.

: 1+            \ n1|u1 -- n2|u2
Add one to top-of stack.

: 2+            \ n1|u1 -- n2|u2
Add two to top-of stack.

: 4+            \ n1|u1 -- n2|u2
Add four to top-of stack.

: 1-            \ n1|u1 -- n2|u2
Subtract one from top-of stack.

: 2-            \ n1|u1 -- n2|u2
Subtract two from top-of stack.

: 4-            \ n1|u1 -- n2|u2
Subtract four from top-of stack.

: 2*            \ x1 -- x2
Multiply top of stack by 2.

: 4*            \ x1 -- x2
Multiply top of stack by 4.

: 2/            \ x1 -- x2
Signed divide top of stack by 2.

: U2/           \ x1 -- x2
Unsigned divide top of stack by 2.

: 4/            \ x1 -- x2
Signed divide top of stack by 4.

: U4/           \ x1 -- x2
Unsigned divide top of stack by 4.

CODE +          \ n1|u1 n2|u2 -- n3|u3
Add two single precision integer numbers.

CODE -          \ n1|u1 n2|u2 -- n3|u3
Subtract two integers. N3|u3=n1|u1-n2|u2.

CODE NEGATE     \ n1 -- n2
Negate an integer.

CODE D+         \ d1 d2 -- d3
Add two double precision integers.

CODE D-         \ d1 d2 -- d3
Subtract two double precision integers. D3=D1-D2.

CODE DNEGATE    \ d1 -- -d1
Negate a double number.

CODE ?NEGATE    \ n1 flag -- n1|n2
If flag is negative, then negate n1.

CODE ?DNEGATE   \ d1 flag -- d1|d2
If flag is negative, then negate d1.

CODE ABS        \ n -- u
If n is negative, return its positive equivalent (absolute value).

CODE DABS       \ d -- ud
If d is negative, return its positive equivalent (absolute value).

CODE D2*        \ xd1 -- xd2
Multiply the given double number by two.

CODE D2/        \ xd1 -- xd2
Divide the given double number by two.

Multiplication

: UM*           \ u1 u2 -- ud
Perform unsigned-multiply between two numbers and return double result.

: *             \ n1 n2 -- n3
Standard signed multiply. N3 = n1 * n2.

: m*            \ n1 n2 -- d
Signed multiply yielding double result.

Division

ARM Cortex provides 32/32 division instructions, but no 64/32 ones. Avoid 64/32 division routines if you can where performance matters.

macro: udiv64_step      \ --
Cross compiler macro to perform one step of the unsigned 64 bit by 32 bit division

code um/mod     \ ud1 u2 -- urem uquot
Slow and short - Full 64 by 32 unsigned division subroutine. This routine uses a loop for code size. This version is commented out by default.

code um/mod     \ ud1 u2 -- urem uquot
Fast and big - Full 64 by 32 unsigned division subroutine. Unrolled for speed. This routine uses 660 bytes of code space using the Thumb-2 instruction set, whereas the ARM32 version uses 920 bytes.

macro: udiv63_step      \ --
Cross compiler macro to perform one step of the unsigned 63 bit by 31 bit division

proc Udiv63/31  \ r0:r1/tos ; 63/31 unsigned divide -> tos=quot, r0=rem
Unsigned division primitive - unrolled for speed. Note that this routine does not handle the top bit of the divisor and dividend correctly. Udiv63/31 is used for signed divide operations for which the top bits are always zero.

CODE FM/MOD     \  d1 n2 -- rem quot ; floored division
Perform a signed division of double number D1 by single number N2 and return remainder and quotient using floored division. See the ANS Forth specification for more details of floored division.

CODE SM/REM     \ d1 n2 -- rem quot ; symmetric division
Perform a signed division of double number D1 by single number N2 and return remainder and quotient using symmetric (normal) division.

CODE /MOD       \ n1 n2 -- rem quot
Signed symmetric division of N1 by N2 single-precision returning remainder and quotient.

: /             \ n1 n2  -- n3
Standard signed division operator. n3 = n1/n2.

: MOD           \ n1 n2 -- n3
Return remainder of division of N1 by N2. n3 = n1 mod n2.

: M/            \ d n1 -- n2
Signed divide of a double by a single integer.

: MU/MOD        \ d n -- rem d#quot
Perform an unsigned divide of a double by a single, returning a single remainder and a double quotient.

Scaling - multiply then divide

These operations perform a multiply followed by a divide. The intermediate result is in an extended form. The point of these operations is to avoid loss of precision.

: */MOD         \ n1 n2 n3 -- n4 n4
Multiply n1 by n2 to give a double precision result, and then divide it by n3 returning the remainder and quotient.

: */            \ n1 n2 n3 -- n4
Multiply n1 by n2 to give a double precision result, and then divide it by n3 returning the quotient.

: m*/           \ d1 n2 n3 -- dquot
The result dquot=(d1*n2)/n3. The intermediate value d1*n2 is triple-precision to avoid loss of precision. In an ANS Forth standard program n3 can only be a positive signed number and a negative value for n3 generates an ambiguous condition, which may cause an error on some implementations, but not in this one.

Stack manipulation

: NIP           \ x1 x2 -- x2
Dispose of the second item on the data stack.

: TUCK          \ x1 x2 -- x2 x1 x2
Insert a copy of the top data stack item underneath the current second item.

CODE PICK       \ xu .. x0 u -- xu .. x0 xu
Get a copy of the Nth data stack item and place on top of stack. 0 PICK is equivalent to DUP.

CODE ROLL       \ xu xu-1 .. x0 u -- xu-1 .. x0 xu
Rotate the order of the top N stack items by one place such that the current top of stack becomes the second item and the Nth item becomes TOS. See also ROT.

: ROT   \ x1 x2 x3 -- x2 x3 x1
ROTate the positions of the top three stack items such that the current top of stack becomes the second item. See also ROLL.

: -ROT  \ x1 x2 x3 -- x3 x1 x2
The inverse of ROT.

CODE >R         \ x -- ; R: -- x
Push the current top item of the data stack onto the top of the return stack.

CODE R>         \ -- x ; R: x --
Pop the top item from the return stack to the data stack.

CODE R@         \ --  x  ; R:  x -- x
Copy the top item from the return stack to the data stack.

CODE 2>R        \ x1 x2 -- ; R:  -- x1 x2
Transfer the two top data stack items to the return stack.

CODE 2R>        \ -- x1 x2 ; R: x1 x2 --
Transfer the top two return stack items to the data stack.

CODE 2R@        \ --  x1 x2  ; R:  x1 x2 -- x1 x2
Copy the top two return stack items to the data stack.

CODE 2ROT       \ x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2
Perform the ROT operation on three cell-pairs.

: SWAP          \ x1 x2 -- x2 x1
Exchange the top two data stack items.

: DUP           \ x -- x x
DUPlicate the top stack item.

: OVER          \ x1 x2 -- x1 x2 x1
Copy NOS to a new top-of-stack item.

: DROP          \ x --
Lose the top data stack item and promote NOS to TOS.

: 2DROP         \ x1 x2 -- )
Discard the top two data stack items.

: 2SWAP         \ x1 x2 x3 x4 -- x3 x4 x1 x2
Exchange the top two cell-pairs on the data stack.

CODE ?DUP       \ x -- | x
DUPlicate the top stack item only if it non-zero.

CODE 2DUP       \ x1 x2 -- x1 x2 x1 x2
DUPlicate the top cell-pair on the data stack.

CODE 2OVER      \ x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2
As OVER but works with cell-pairs rather than single-cell items.

CODE SP@        \ -- x
Get the current address value of the data-stack pointer.

CODE SP!        \ x --
Set the current address value of the data-stack pointer.

CODE RP@        \ -- x
Get the current address value of the return-stack pointer.

CODE RP!        \ x --
Set the current address value of the return-stack pointer.

String and memory operators

: COUNT         \ c-addr1 -- c-addr2' u
Given the address of a counted string in memory this word will return the address of the first character and the length in characters of the string.

CODE /STRING    \ c-addr1 u1 n -- c-addr2 u2
Modify a string address and length to remove the first N characters from the string.

CODE SKIP       \ c-addr1 u1 char -- c-addr2 u2
Modify the string description by skipping over leading occurrences of 'char'.

CODE SCAN       \ c-addr1 u1 char -- c-addr2 u2
Look for first occurrence of char in the string and return a new string. C-addr2/u2 describes the string with char as the first character.

CODE S=         \ c-addr1 c-addr2 u -- flag
Compare two same-length strings/memory blocks, returning TRUE if they are identical.

: compare       \ c-addr1 u1 c-addr2 u2 -- n                    17.6.1.0935
Compare two strings. The return result is 0 for a match or can be -ve/+ve indicating string differences. If the two strings are identical, n is zero. If the two strings are identical up to the length of the shorter string, n is minus-one (-1) if u1 is less than u2 and one (1) otherwise. If the two strings are not identical up to the length of the shorter string, n is minus-one (-1) if the first non-matching character in the string specified by c-addr1 u1 has a lesser numeric value than the corresponding character in the string specified by c-addr2 u2 and one (1) otherwise.

: SEARCH        ( c-addr1 u1 c-addr2 u2 -- c-addr3 u3 flag  )
Search the string c-addr1/u1 for the string c-addr2/u2. If a match is found return c-addr3/u3, the address of the start of the match and the number of characters remaining in c-addr1/u1, plus flag f set to true. If no match was found return c-addr1/u1 and f=0.

code cmove      \ asrc adest len --
Copy len bytes of memory forwards from asrc to adest. If the performance of CMOVE is important in your application, set the equate FastCmove? non-zero and a much faster (four to five times) but much larger (~900 bytes) version will be compiled. See Cortex\fcmove.fth for the details.

CODE CMOVE>     \ c-addr1 c-addr2 u --
As CMOVE but working in the opposite direction, copying the last character in the string first.

: ON            \ a-addr --
Given the address of a CELL this will set its contents to TRUE (-1).

: OFF           \ a-addr --
Given the address of a CELL this will set its contents to FALSE (0).

CODE C+!        \ b c-addr --
Add N to the character (byte) at memory address ADDR.

CODE 2@         \ a-addr -- x1 x2
Fetch and return the two CELLS from memory ADDR and ADDR+sizeof(CELL). The cell at the lower address is on the top of the stack.

CODE 2!         \ x1 x2 a-addr --
Store the two CELLS x1 and x2 at memory ADDR. X2 is stored at ADDR and X1 is stored at ADDR+CELL.

CODE FILL       \ c-addr u char --
Fill LEN bytes of memory starting at ADDR with the byte information specified as CHAR.

CODE +!         \ n|u a-addr --
Add N to the CELL at memory address ADDR.

CODE INCR       \ a-addr --
Increment the data cell at a-addr by one.

CODE DECR       \ a-addr --
Decrement the data cell at a-addr by one.

CODE @          \ a-addr -- x
Fetch and return the CELL at memory ADDR.

CODE W@         \ a-addr -- w
Fetch and 0 extend the word (16 bit) at memory ADDR.

CODE C@         \ c-addr -- char
Fetch and 0 extend the character at memory ADDR and return.

CODE !          \ x a-addr --
Store the CELL quantity X at memory A-ADDR.

CODE W!         \ w a-addr --
Store the word (16 bit) quantity w at memory ADDR.

CODE C!         \ char c-addr --
Store the character CHAR at memory C-ADDR.

: UPC           \ char -- char'
Convert supplied character to upper case if it was alphabetic otherwise return the unmodified character. UPC is English language specific.

CODE UPPER      \ c-addr u --
Convert the ASCII string described to upper-case. This operation happens in place.

CODE TEST-BIT   \ mask c-addr -- flag
AND the mask with the contents of addr and return true if the result is non-zero (-1) or false (0) if the result is zero. Byte operation.

CODE SET-BIT    \ mask c-addr --
Apply the mask ORred with the contents of c-addr. Byte operation.

CODE RESET-BIT  \ mask c-addr --
Apply the mask inverted and ANDed with the contents of c-addr. Byte operation.

CODE TOGGLE-BIT \ u c-addr --
Invert the bits at c-addr specified by the mask. Byte operation.

Miscellaneous words

CODE NAME>      \ nfa -- cfa
Move a pointer from an NFA to the XT..

CODE >NAME      \ cfa -- nfa
Move a pointer from an XT back to the NFA or name-pointer. If the original pointer was not an XT or if the definition in question has no name header in the dictionary the returned pointer will be useless. Care should be taken when manipulating or scanning the Forth dictionary in this way.

: SEARCH-WORDLIST       \ c-addr u wid -- 0|xt 1|xt -1
Search the given wordlist for a definition. If the definition is not found then 0 is returned, otherwise the XT of the definition is returned along with a non-zero code. A -ve code indicates a "normal" definition and a +ve code indicates an IMMEDIATE word.

CODE DIGIT      \ char base -- 0|n true
If the ASCII value CHAR can be treated as a digit for a number within the radix base then return the digit and a TRUE (-1) flag, otherwise return FALSE (0).

Portability helpers

Using these words will make code easier to port between 16, 32 and 64 bit targets.

CODE CELL+      \ a-addr1 -- a-addr2
Add the size of a CELL to the top-of stack.

CODE CELLS      \ n1 -- n2
Return the size in address units of N1 cells in memory.

CODE CELL-      \ a-addr1 -- a-addr2
Decrement an address by the size of a cell.

CODE CELL       \ -- n
Return the size in address units of one CELL.

CODE CHAR+      \ c-addr1 -- c-addr2
Increment an address by the size of a character.

: CHARS         \ n1 -- n2
Return size in address units of N1 characters.

Runtime for VALUE

CODE VAL!       \ n -- ; store value address in-line
Store n at the inline address following this word. INTERNAL.

CODE VAL@       \ -- n ; read value data address in-line
Read n from the inline address following this word. INTERNAL.

Supporting complation on the target

Compilation on the target is supported for compilation into RAM. The target's compiler is simplistic and gives neither the code size nor the performance of cross-compiled code. The support words are compiled without heads.

Direct compilation into Flash requires additional code. If you need it and want support, please contact MPE.

: !scall        \ dest addr --
Patch a BL DEST opcode at addr.

: !lcall        \ dest addr --
Patch n MVL32 R0, # DEST+1 opcode at addr.

Defining words and runtime support

L: DOCREATE     \ -- addr
The run time action of CREATE. The call must be on a four byte boundary. INTERNAL.

CODE LIT        \ -- x
Code which when CALLED at runtime will return an inline cell value. The call must be at a four byte boundary. INTERNAL.

CODE (")        \ -- a-addr ; return address of string, skip over it
Return the address of a counted string that is inline after the CALLING word, and adjust the CALLING word's return address to step over the inline string. The adjusted return address will be at a four byte boundary. See the definition of (.") for an example.

code (z")       \ -- zaddr
Return the address of the following counted and zero-terminated string. Step over the string and the trailing zero.

: aligned       \ addr -- addr'
Given an address pointer this word will return the next ALIGNED address subject to system wide alignment restrictions.

: compile,      \ xt --
Compile the word specified by xt into the current definition.

: >BODY         \ xt -- a-addr
Move a pointer from a CFA or "XT" to the definition BODY. This should only be used with children of CREATE. E.g. if FOOBAR is defined by CREATE foobar, then the phrase ' foobar >body would yield the same result as executing foobar.

: DOCREATE,     \ --
Compile the run time action of CREATE. INTERNAL.

: (;CODE)       \ -- ; R: a-addr --
Performed at compile time by ;CODE and DOES>. Patch the last word defined (by CREATE) to have the run time actions that follow immediately after (;CODE). INTERNAL.

: (;CODE)       \ -- ; R: a-addr --
Performed at compile time by ;CODE and DOES>. Patch the last word defined (by CREATE) to have the run time actions that follow immediately after (;CODE). INTERNAL.

: CONSTANT      \ x "<spaces>name" -- ; Exec: -- x
Create a new CONSTANT called name which has the value x. When NAME is executed x is returned.

: 2CONSTANT     \ Comp: x1 x2 "<spaces>name" -- ; Run: -- x1 x2
A two-cell equivalent of CONSTANT.

: VARIABLE      \ "<spaces>name" -- ; Exec: -- a-addr
Create a new variable called name. When name is executed the address of the data-cell is returned for use with @ and ! operators.

: 2VARIABLE     \ Comp: "<spaces>name" -- ; Run: -- a-addr
A two-cell equivalent of VARIABLE.

: USER          \ u "<spaces>name" -- ; Exec: -- addr ; SFP009
Create a new USER variable called name. The u parameter specifies the index into the user-area table at which to place the* data. USER variables are located in a separate area of memory for each task or interrupt. Use in the form:

  $400 USER TaskData

: u#            \ "<name>"-- u
An INTERPRETER word that returns the index of the USER variable whose name follows, e.g.

  u# S0

: :             \ C: "<spaces>name" -- colon-sys ; Exec: i*x -- j*x ; R: -- nest-sys
Begin a new definition called name.

: :NONAME       \ C: -- colon-sys ; Exec: i*x -- i*x  ; R: -- nest-sys
Begin a new code definition which does not have a name. After the definition is complete the semi-colon operator returns the XT of newly compiled code on the stack.

: DOES>         \ C: colon-sys1 -- colon-sys2 ; Run: -- ; R:  nest-sys --
Begin definition of the runtime-action of a child of a defining word. See the section about defining words in Programming Forth. You should not use RECURSE after DOES>.

: CRASH         \ -- ; used as action of DEFER
The default action of a DEFERed word, which is to perform #12 THROW. INTERNAL.

: DEFER         \ Comp: "<spaces>name" -- ; Run:  i*x -- j*x
Creates a new DEFERed word. A default action, CRASH, is assigned.

: (TO-DO)       \ -- ; R: xt -- a-addr'
The run-time action of TO-DO. It is followed by the data address of the DEFERred word at which the xt is stored.

: FIELD         \ size n "<spaces>name" -- size+n ; Exec: addr -- addr+n
Create a new field of n bytes within a structure so far of size bytes.

Structure compilation

These words define high level branches. They are used by the structure words such as IF and AGAIN.

: >mark         \ -- addr
Mark the start of a forward branch. HIGH LEVEL CONSTRUCTS ONLY. INTERNAL.

: >resolve      \ addr --
Resolve absolute target of forward branch. HIGH LEVEL CONSTRUCTS ONLY. INTERNAL.

: <mark         \ -- addr
Mark the start (destination) of a backward branch. HIGH LEVEL CONSTRUCTS ONLY. INTERNAL.

: <resolve      \ addr --
Resolve a backward branch to addr. HIGH LEVEL CONSTRUCTS ONLY. INTERNAL.

synonym >c_res_branch >resolve  \ addr -- ; fix up forward referenced branch
See >RESOLVE. INTERNAL.

synonym c_mrk_branch< <mark     \ -- addr ; mark destination of backward branch
See <MARK. INTERNAL.

Branch constructors

Used when compiling code on the target.

: c_branch<     \ addr --
Lay the code for an unconditional backward branch. INTERNAL.

: c_?branch<    \ addr --
Lay the code for a conditional backward branch.

: c_branch>     \ -- addr
Lay the code for a forward referenced unconditional branch. INTERNAL.

: c_?branch>    \ -- addr
Lay the code for a forward referenced conditional branch. INTERNAL.

Main compilers

: c_lit         \ lit --
Compile the code for a literal of value lit. INTERNAL.

: c_drop        \ --
Compile the code for DROP. INTERNAL.

: c_exit        \ --
Compile the code for EXIT. INTERNAL.

: c_do          \ C: -- do-sys ; Run: n1|u1 n2|u2 -- ; R: -- loop-sys
Compile the code for DO. INTERNAL.

: c_?DO         \ C: -- do-sys ; Run: n1|u1 n2|u2 -- ; R: -- | loop-sys
Compile the code for ?DO. INTERNAL.

: c_LOOP        \ C: do-sys -- ; Run: -- ; R: loop-sys1 -- | loop-sys2
Compile the code for LOOP. INTERNAL.

: c_+LOOP       \ C: do-sys -- ; Run: -- ; R: loop-sys1 -- | loop-sys2
Compile the code for +LOOP. INTERNAL.

variable NextCaseTarg   \ -- addr
Holds the entry point of the current CASE structure. INTERNAL.

: c_case        \ -- addr
Compile the code for CASE. INTERNAL.

: c_OF          \ C: -- of-sys ; Run: x1 x2 -- | x1
Compile the code for OF. INTERNAL.

: c_ENDOF       \ C: case-sys1 of-sys -- case-sys2 ; Run: --
Compile the code for ENDOF. INTERNAL.

: FIX-EXITS     \ n1..nn --
Compile the code to resolve the forward branches at the end of a CASE structure. INTERNAL.

: c_ENDCASE     \ C: case-sys -- ; Run: x --
Compile the code for ENDCASE. INTERNAL.

: c_END-CASE    \ C: case-sys -- ; Run: x --
Compile the code for END-CASE. INTERNAL. Only compiled if the equate FullCase? is non-zero.

: c_NEXTCASE    \ C: case-sys -- ; Run: x --
Compile the code for NEXTCASE. INTERNAL. Only compiled if the equate FullCase? is non-zero.

: c_?OF         \ C: -- of-sys ; Run: flag --
Compile the code for ?OF. INTERNAL. Only compiled if the equate FullCase? is non-zero.

Miscellaneous

code di         \ --
Disable interrupts.

code ei         \ --
Enable interrupts.

code dfi        \ --
Disable fault exceptions.

code efi                \ --
Enable fault exceptions.

code [I         \ R: -- x1 x2
Preserve interrupt/exception status on the return stack, and disable interrupts/exceptions except reset, NMI and HardFault. The state is restored by I].

code I]         \ R: x1 x2 --
Restore interrupt status saved by [I from the return stack.

code clz        \ x -- #lz
Count the number of leading zeros in x.

code dsqrt      \ +d -- n
Single square root of a double number. 62 bits -> 31 bits. The equate DSQRT? must be set true to compile this word.

: setMask       \ value mask addr -- ; cell operation
Clear the mask bits at addr and set (or) the bits defined by value.

: init-io       \ addr --
Copy the contents of the I/O set up table to an I/O device. Each element of the table is of the form addr (cell) followed by data (cell). The table is terminated by an address of 0.