The file Cortex/MinCortex.fth contains the minimum code definitions required to support Umbilical Forth. If additional words are required, they may be copied to a new file from Cortex/CodeCortex.fth or Common/Kernel62.fth.
For Cortex-M3+ 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 --
r7 tos cached top of stack
r0-r6 scratch
The VFX optimiser reserves R0 and R1 for internal operations.
CODE
definitions must use R10 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.
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.
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 EXECUTE \ xt --
Execute the code described by the XT. This is a Forth equivalent
to an assembler JSR/CALL instruction.
CODE NOOP \ --
A NOOP, null instruction. )
: DROP \ x --
Lose the top data stack item and promote NOS to TOS.
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.
: 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.
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.
: */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. The point
of this operation is to avoid loss of precision.
: */ \ n1 n2 n3 -- n4
Multiply n1 by n2 to give a double precision result, and then
divide it by n3 returning the quotient. The point
of this operation is to avoid loss of precision.
: M/ \ d n1 -- n2
Signed divide of a double by a single 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 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
.
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.
CODE FILL \ c-addr u char --
Fill LEN bytes of memory starting at ADDR with the byte information
specified as CHAR.
: erase \ c-addr u -- ; wipe memory
Set U bytes of memory starting at C-ADDR with zeros.
CODE S= \ c-addr1 c-addr2 u -- flag
Compare two same-length strings/memory blocks, returning TRUE if
they are identical.
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.
: (C") \ -- c-addr
The run time action compiled by C".
: (S") \ -- c-addr u
The run time action compiled by S".
here is-action-of constant
The runtime code for a CONSTANT.
here is-action-of variable
The runtime action for a VARIABLE.
here is-action-of value
The runtime action of a VALUE.
here is-action-of user
The runtime action of a USER variable.
: u# \ "<name>"-- u
An INTERPRETER
word that returns the index of the
USER
variable whose name follows, e.g.
u# S0
: CRASH \ -- ; used as action of DEFER
The default action of a DEFERed word. A NOOP.
here is-action-of DEFER \ Comp: "<spaces>name" -- ; Run: i*x -- j*x
The runtime action of a DEFERred word.
: SPACE \ --
Output a blank space (ASCII 32) character.
: SPACES \ n --
Output 'n' spaces, where 'n' > 0.
If 'n' < 0, no action is taken.
: .nibble \ n --
Convert a nibble to a hex ASCII digit and display it.
: .BYTE \ b --
Display the byte b as a 2 digit hex number.
: .WORD \ w --
Display w as a 4 digit unsigned hexadecimal number.
: .dword \ x --
Display x as an 8 digit unsigned hexadecimal number.
: .lword \ x --
A synonym for .DWORD
above.