umouse

umouse.git
git clone git://git.lenczewski.org/umouse.git
Log | Files | Refs | Submodules | README

CodeM0lite.fth (62772B)


      1 \ CodeM0lite.fth - ARM Cortex-M0 code file
      2 
      3 ((
      4 Copyright (c) 2009, 2010, 2011, 2014
      5 MicroProcessor Engineering
      6 133 Hill Lane
      7 Southampton SO15 5AF
      8 England
      9 
     10 tel: +44 (0)23 8063 1441
     11 fax: +44 (0)23 8033 9691
     12 net: mpe@mpeforth.com
     13      tech-support@mpeforth.com
     14 web: www.mpeforth.com
     15 
     16 From North America, our telephone and fax numbers are:
     17   011 44 23 8063 1441
     18   011 44 23 8033 9691
     19 
     20 
     21 To do
     22 =====
     23 Recode FILL to check for word start address, and copy words if possible.
     24 This change may have a good speed/size trade-off.
     25 
     26 Change history
     27 ==============
     28 20140107 SFP006 Corrected FM/MOD.
     29 20110601 SFP005 Cortex M0/M1 conversion.
     30 20100430 SFP004 Corrected !LCALL and (;CODE).
     31 20100427 SFP003 Corrected ROLL.
     32 20100108 MPE002 First release
     33 20091209 SFP001 Started
     34 ))
     35 
     36 \ ==========
     37 \ *! codem0m1lite
     38 \ *T Cortex code definitions
     39 \ ==========
     40 \ *P The file *\i{Cortex/CodeM0lite.fth} contains primitives for
     41 \ ** the standalone Lite Forth kernel.
     42 
     43 \ ********
     44 \ *S Notes
     45 \ ********
     46 \ *P Some words and code routines are marked in the documentation
     47 \ ** as *\fo{INTERNAL}. These are factors used by other words and do
     48 \ ** not have dictionary entries in the standalone Forth. They
     49 \ ** are only accessible to users of the VFX Forth ARM Cross
     50 \ ** Compiler. This also applies to definitions of the form:
     51 \ *C n EQU <name>
     52 \ *C PROC <name>
     53 \ *C L: <name>
     54 
     55 \ *****************
     56 \ *S Register usage
     57 \ *****************
     58 \ *P For Cortex-M0/M1 the following register usage is the default:
     59 \ *E   r15         pc      program counter
     60 \ **   r14         link    link register; bit0=1=Thumb, usually set
     61 \ **   r13         rsp     return stack pointer
     62 \ **   r12         --
     63 \ **   r11         up      user area pointer
     64 \ **   r10         --
     65 \ **   r9          lp      locals pointer
     66 \ **   r8          --
     67 \ **   r7          tos     cached top of stack
     68 \ **   r6          psp     data stack pointer
     69 \ **   r0-r5       scratch
     70 \ *P The VFX optimiser reserves R0 and R1 for internal operations.
     71 \ ** *\fo{CODE} definitions must use R7 as TOS with NOS pointed
     72 \ ** to by R6 as a full descending stack in ARM terminology.
     73 \ ** R0..R5, R12 are free for use by *\fo{CODE} definitions and
     74 \ ** need not be preserved or restored. You should assume that
     75 \ ** any register can be affected by other words.
     76 
     77 only forth definitions
     78 decimal
     79 
     80 
     81 \ ***********************************
     82 \ *S Logical and relational operators
     83 \ ***********************************
     84 
     85 : AND		\ x1 x2 -- x3
     86 \ *G Perform a logical AND between the top two stack items and retain
     87 \ ** the result in top of stack.
     88   and  ;
     89 
     90 : OR		\ x1 x2 -- x3
     91 \ *G Perform a logical OR between the top two stack items and retain
     92 \ ** the result in top of stack.
     93   or  ;
     94 
     95 : XOR		\ x1 x2 -- x3
     96 \ *G Perform a logical XOR between the top two stack items and retain
     97 \ ** the result in top of stack.
     98   xor  ;
     99 
    100 : INVERT 	\ x -- x'
    101 \ *G Perform a bitwise inversion.
    102   invert  ;
    103 
    104 : 0=	 	\ x -- flag
    105 \ *G Compare the top stack item with 0 and return TRUE if equals.
    106   0=  ;
    107 
    108 : 0<> 		\ x -- flag
    109 \ *G Compare the top stack item with 0 and return TRUE if not-equal.
    110   0<>  ;
    111 
    112 : 0<	 	\ x -- flag
    113 \ *G Return TRUE if the top of stack is less-than-zero.
    114   0<  ;
    115 
    116 : 0> 		\ x -- flag
    117 \ *G Return TRUE if the top of stack is greater-than-zero.
    118   0>  ;
    119 
    120 : = 		\ x1 x2 -- flag
    121 \ *G Return TRUE if the two topmost stack items are equal.
    122   =  ;
    123 
    124 : <> 		\ x1 x2 -- flag
    125 \ *G Return TRUE if the two topmost stack items are different.
    126   <>  ;
    127 
    128 : < 		\ n1 n2 -- flag
    129 \ *G Return TRUE if n1 is less than n2.
    130   <  ;
    131 
    132 : > 		\ n1 n2 -- flag
    133 \ *G Return TRUE if n1 is greater than n2.
    134   >  ;
    135 
    136 : <= 		\ n1 n2 -- flag
    137 \ *G Return TRUE if n1 is less than or equal to n2.
    138   <=  ;
    139 
    140 : >= 		\ x1 x2 -- flag
    141 \ *G Return TRUE if n1 is greater than or equal to n2.
    142   >=  ;
    143 
    144 : U> 		\ u2 u2 -- flag
    145 \ *G An UNSIGNED version of >.
    146   u>  ;
    147 
    148 : U< 		\ u1 u2 -- flag
    149 \ *G An UNSIGNED version of <.
    150   u<  ;
    151 
    152 : D0<	 	\ d -- flag
    153 \ *G Returns true if signed double d is less than zero.
    154   nip 0<  ;
    155 
    156 : D0=	\ xd -- flag
    157 \ *G Returns true if xd is 0.
    158   or  0=  ;
    159 
    160 CODE D= 	\ xd1 xd2 -- flag
    161 \ *G Return TRUE if the two double numbers are equal.
    162   ldmia psp ! { r0-r2 }                 \ r0=d2 low, r1=d1 high, r2=d1 low
    163   mov .s r3, tos			\ r3=d2h
    164   mov .s tos, # 0			\ assume false
    165   sub .s r0, r0, r2                     \ d2l - d1l
    166   sbc .s r3, r3, r1			\ d2h - d1h
    167   orr .s r0, r0, tos
    168   eq, if,
    169     mvn .s tos, tos			\ true
    170   endif,
    171   next,
    172 END-CODE
    173 
    174 ((
    175 CODE D< 	\ d1 d2 -- flag
    176  \ *G Return TRUE if the double number d1 is (signed) less than the
    177  \ ** double number d2.
    178   ldmia psp ! { r0-r2 }                 \ r0=d2 low, r1=d1 high, r2=d1 low
    179   mov .s r3, tos			\ r3=d2h
    180   mov .s tos, # 0			\ assume false
    181   sub .s r2, r2, r0                     \ d1l - d2l
    182   sbc .s r1, r1, r3			\ d1h - d2h
    183   lt, if,
    184     mvn .s  tos, tos			\ true
    185   endif,
    186   next,
    187 END-CODE
    188 
    189 : D> 		\ d1 d2 -- flag
    190  \ *G Return TRUE if the double number d1 is (signed) greater than the
    191  \ ** double number d2.
    192   2swap d<  ;
    193 ))
    194 
    195 ((
    196 CODE DU< 	\ ud1 ud2 -- flag
    197  \ *G Returns true if ud1 (unsigned double) is less than ud2.
    198   ldmia psp ! { r0-r2 }                 \ r0=d2 low, r1=d1 high, r2=d1 low
    199   mov .s r3, tos			\ r3=d2h
    200   mov .s tos, # 0			\ assume false
    201   sub .s r2, r2, r0                     \ d1l - d2l
    202   sbc .s r1, r1, r3			\ d1h - d2h
    203   cc, if,
    204     mvn .s tos, tos
    205   endif,
    206   next,
    207 END-CODE
    208 
    209 : DU>	 	\ ud1 ud2 -- flag
    210  \ *G Returns true if ud1 (unsigned double) is greater than ud2.
    211   2swap du<  ;
    212 ))
    213 ((
    214 : DMAX 	\ d1 d2 -- d3 ; d3=max of d1/d2
    215  \ *G Return the maximum double number from the two supplied.
    216   2over 2over d<
    217   if  2swap  then
    218   2drop
    219 ;
    220 
    221 : DMIN 	\ d1 d2 -- d3 ; d3=min of d1/d2
    222  \ *G Return the minimum double number from the two supplied.
    223   2over 2over d>
    224   if  2swap  then
    225   2drop
    226 ;
    227 ))
    228 
    229 CODE MIN	\ n1 n2 -- n1|n2
    230 \ *G Given two data stack items preserve only the smaller.
    231   ldmia   psp, ! { r0 }
    232   cmp     tos, r0
    233   gt, if,
    234     mov     tos, r0
    235   endif,
    236   next,
    237 END-CODE
    238 
    239 CODE MAX	\ n1 n2 -- n1|n2
    240 \ *G Given two data stack items preserve only the larger.
    241   ldmia   psp, ! { r0 }
    242   cmp     tos, r0
    243   lt, if,
    244     mov  tos, r0
    245   endif,
    246   next,
    247 END-CODE
    248 
    249 ((
    250 CODE WITHIN? 	\ n1 n2 n3 -- flag
    251  \ *G Return TRUE if N1 is within the range N2..N3.
    252  \ ** This word uses signed arithmetic.
    253   ldmia   psp ! { r0, r1 }
    254   mov .s  r2, # 0
    255   mov .s  r3, # 0
    256   cmp     r1, r0
    257   ge, if,
    258     mov .s  r2, # 1
    259   endif,
    260   cmp     r1, tos
    261   le, if,
    262     mov .s  r3, # 1
    263   endif,
    264   mov .s  tos, # 0		\ flag=0
    265   tst     r2, r3
    266   ne, if,
    267     mvn .s  tos, tos		\ flag=-1
    268   endif,
    269   next,
    270 END-CODE
    271 ))
    272 
    273 : within	\ n1|u1 n2|u2 n3|u3 -- flag
    274 \ *G Return true for *\i{n2 <= n1 < n3}.
    275 \ ** This word uses unsigned arithmetic, so that signed compares are
    276 \ ** treated as existing on a number circle.
    277   over - -rot			\ -- n3-n2 n1 n2
    278   -				\ -- n3-n2 n1-n2
    279   swap u<			\ (n1-n2)-(n3-n2), cy -> -1, ncy -> 0
    280 ;
    281 
    282 code lshift 	\ x1 u -- x2
    283 \ *G Logically shift X1 by U bits left.
    284   mov     r0, tos
    285   ldmia   psp ! { tos }
    286   lsl .s  tos, r0
    287   next,
    288 end-code
    289 
    290 code rshift 	\ x1 u -- x2
    291 \ *G Logically shift X1 by U bits right.
    292   mov     r0, tos
    293   ldmia   psp ! { tos }
    294   lsr .s  tos, r0
    295   next,
    296 end-code
    297 
    298 code arshift 	\ x1 u -- x2
    299 \ *G Arithmetic shift right X1 by U bits.
    300   mov     r0, tos
    301   ldmia   psp ! { tos }
    302   asr .s  tos, r0
    303   next,
    304 end-code
    305 
    306 
    307 \ ***************
    308 \ *S Control flow
    309 \ ***************
    310 
    311 CODE EXECUTE 	\ xt --
    312 \ *G Execute the code described by the XT. This is a Forth equivalent
    313 \ ** of an assembler JSR/CALL instruction.
    314   mov .s  r0, # 1
    315   orr .s  r0, tos		        \ move CFA, setting Thumb bit
    316   ldmia   psp ! { tos }
    317   bx      r0				\ execute CFA - link contains ret addr of execute
    318 END-CODE
    319 
    320 internal
    321 
    322 CODE BRANCH	\ --
    323 \ +G The run time action of unconditional branches compiled on the target.
    324 \ +* The branch target address is in-line and must have the T bit set.
    325 \ +* INTERNAL.
    326 l: takebranch
    327   mov .s  r1, # 1
    328   mov     r0, link
    329   bic .s  r0, r1
    330   ldr     r2, [ r0 ]			\ get address and branch
    331   bx      r2
    332 END-CODE
    333 
    334 CODE ?BRANCH	\ n --
    335 \ +G The run time action of conditional branches compiled on the target.
    336 \ +* The branch target address is in-line and must have the T bit set.
    337 \ +* INTERNAL.
    338   mov .s  r1, tos
    339   ldmia   psp ! { tos }
    340   b .eq   takebranch
    341 l: skipbranch
    342   mov     r0, link
    343   add .s  r0, # 4
    344   bx      r0
    345 END-CODE
    346 
    347 CODE (OF) 	\ n1 n2 -- n1|--
    348 \ +G The run time action of OF compiled on the target.
    349 \ +* The branch target address is in-line and must have the T bit set.
    350 \ +* INTERNAL.
    351   ldmia   psp ! { r0 }			\ get n1
    352   cmp     r0, tos			\ compare n1 and n2
    353   b .ne   takebranch
    354   ldmia   psp ! { tos }			\ equal so get new tos
    355   b       skipbranch
    356 END-CODE
    357 
    358 CODE (LOOP) 	\ --
    359 \ +G The run time action of *\fo{LOOP} compiled on the target.
    360 \ +* The branch target address is in-line and must have the T bit set.
    361 \ +* INTERNAL.
    362   ldr     r1, [ rsp ]			\ fetch index
    363   add .s  r1, r1, # 1			\ increment index
    364   str     r1, [ rsp ]			\ store new index]
    365   b .vc   takebranch
    366   add     rsp, rsp, # $0C		\ drop 3 items from return stack
    367   b       skipbranch
    368 END-CODE
    369 
    370 CODE (+LOOP) 	\ n --
    371 \ +G The run time action of *\fo{+LOOP} compiled on the target.
    372 \ +* The branch target address is in-line and must have the T bit set.
    373 \ +* INTERNAL.
    374   ldr    r1, [ rsp ]			\ fetch index
    375   add .s r1, r1, tos                    \ increment index by n
    376   str    r1, [ rsp ]			\ store new index
    377   ldmia   psp ! { tos }			\ update tos
    378   b .vc   takebranch
    379   add     rsp, rsp, # $0C		\ drop 3 items from return stack
    380   b       skipbranch
    381 END-CODE
    382 
    383 CODE (DO)	\ limit index --
    384 \ +G The run time action of *\fo{DO} compiled on the target.
    385 \ +* The branch target address is in-line and must have the T bit set.
    386 \ +* INTERNAL.
    387   ldmia   psp ! { r1 }			\ get limit
    388 L: PDO
    389   mov .s  r4, # 1
    390   lsl .s  r4, r4, # #31			\ r4 := $8000:0000
    391   mov     r3, link
    392   sub .s  r3, r3, # 1			\ clear T bit
    393   ldr     r2, [ r3 ]			\ get LEAVE address, compiler sets T bit
    394   add .s  r1, r1, r4			\ limit+$8000:0000
    395   sub .s  r0, tos, r1			\ index-limit-$8000:0000
    396 
    397   push    { r0, r1, r2 }		\ push LEAVE then limit, then index on ret. stack
    398   ldmia   psp ! { tos }			\ update tos
    399   b       skipbranch
    400 END-CODE
    401 
    402 CODE (?DO) 	\ limit index --
    403 \ +G The run time action of *\fo{?DO} compiled on the target.
    404 \ +* The branch target address is in-line and must have the T bit set.
    405 \ +* INTERNAL.
    406   ldmia   psp ! { r1 }			\ get limit
    407   cmp     r1, tos			\ check not equal
    408   b .ne   pdo				\ take DO ?
    409   ldmia   psp ! { tos }			\ update tos
    410   b       takebranch
    411 END-CODE
    412 
    413 external
    414 
    415 CODE LEAVE 	\ --
    416 \ *G Remove the current *\fo{DO..LOOP} parameters and jump to the
    417 \ ** end of the *\fo{DO..LOOP} structure.
    418   add     rsp, rsp, # 8			\ remove limit, index
    419   pop     { pc }			\ jump to exit address, Thumb bit set by DO/?DO
    420 END-CODE
    421 
    422 CODE ?LEAVE 	\ flag --
    423 \ *G If flag is non-zero, remove the current *\fo{DO..LOOP} parameters
    424 \ ** and jump to the end of the *\fo{DO..LOOP} structure.
    425   mov .s  tos, tos                      \ set flags
    426   ldmia   psp ! { tos }			\ update tos
    427   eq, if,
    428     bx      r14				\ flag false so continue
    429   endif,
    430   add rsp, rsp, # 8                     \ flag true so remove limit, index  - if old TOS<>0
    431   pop     { pc }			\ flag true so jump to exit address
    432 END-CODE
    433 
    434 CODE I		\ -- n
    435 \ *G Return the current index of the inner-most DO..LOOP.
    436   sub .s  psp, psp, # 4
    437   str     tos, [ psp ]
    438   ldr     tos, [ rsp, # 0 ]
    439   ldr     r0, [ rsp, # 4 ]
    440   add .s  tos, tos, r0
    441   next,
    442 END-CODE
    443 
    444 CODE J 		\ -- n
    445 \ *G Return the current index of the second DO..LOOP.
    446   sub .s  psp, psp, # 4
    447   str     tos, [ psp ]
    448   ldr     tos, [ rsp, # $0C ]		\ index
    449   ldr     r0, [ rsp, # $010 ]
    450   add .s  tos, tos, r0
    451   next,
    452 END-CODE
    453 
    454 CODE UNLOOP 	\ -- ; R: loop-sys --
    455 \ *G Remove the DO..LOOP control parameters from the return stack.
    456   add     rsp, rsp, # $0C		\ remove loop parameters from return stack
    457   next,                                 \ jump to return address
    458 END-CODE
    459 
    460 
    461 \ *******************
    462 \ *S Basic arithmetic
    463 \ *******************
    464 
    465 : S>D 	\ n -- d
    466 \ *G Convert a single number to a double one.
    467   s>d  ;
    468 
    469 ((
    470 : D>S	 	\ d -- n
    471  \ *G Convert a double number to a single.
    472   drop  ;
    473 ))
    474 
    475 : NOOP  ;	\ --
    476 \ *G A NOOP, null instruction.
    477 
    478 CODE M+     \ d1|ud1 n -- d2|ud2
    479 \ *G Add double d1 to sign extended single n to form double d2.
    480    ldmia  psp ! { r0 r1 }		\ r0 = d1 high, r1 = d1 low
    481    asr .s r2, tos, # 31			\ d2h = sex(n)
    482    add .s r1, r1, tos                   \ d2l = d1l + n
    483    adc .s r0, r0, r2			\ d2h = d1h + d2h + c
    484    mov    tos, r0
    485    sub .s psp, psp, # 4
    486    str    r1, [ psp ]
    487    next,
    488 END-CODE
    489 
    490 : 1+	 	\ n1|u1 -- n2|u2
    491 \ *G Add one to top-of stack.
    492   1 +  ;
    493 
    494 : 1-	 	\ n1|u1 -- n2|u2
    495 \ *G Subtract one from top-of stack.
    496   1 -  ;
    497 
    498 ((
    499 : 2+		\ n1|u1 -- n2|u2
    500  \ *G Add two to top-of stack.
    501   2 +  ;
    502 
    503 : 4+	 	\ n1|u1 -- n2|u2
    504  \ *G Add four to top-of stack.
    505   4 +  ;
    506 
    507 : 2-	 	\ n1|u1 -- n2|u2
    508  \ *G Subtract two from top-of stack.
    509   2 -  ;
    510 
    511 : 4-	 	\ n1|u1 -- n2|u2
    512  \ *G Subtract four from top-of stack.
    513   4 -  ;
    514 
    515 : 2*		\ x1 -- x2
    516  \ *G Multiply top of stack by 2.
    517   1 lshift  ;
    518 
    519 : 4*		\ x1 -- x2
    520  \ *G Multiply top of stack by 4.
    521   2 lshift  ;
    522 
    523 : 2/		\ x1 -- x2
    524  \ *G Signed divide top of stack by 2.
    525   1 arshift  ;
    526 
    527 : U2/		\ x1 -- x2
    528  \ *G Unsigned divide top of stack by 2.
    529   1 rshift  ;
    530 
    531 : 4/		\ x1 -- x2
    532  \ *G Signed divide top of stack by 4.
    533   2 arshift  ;
    534 
    535 : U4/		\ x1 -- x2
    536  \ *G Unsigned divide top of stack by 4.
    537   2 rshift  ;
    538 ))
    539 
    540 CODE +  	\ n1|u1 n2|u2 -- n3|u3
    541 \ *G Add two single precision integer numbers.
    542   ldr     r0, [ psp ]
    543   add .s  psp, psp, # 4
    544   add .s  tos, tos, r0
    545   next,
    546 END-CODE
    547 
    548 CODE -  	\ n1|u1 n2|u2 -- n3|u3
    549 \ *G Subtract two integers. N3|u3=n1|u1-n2|u2.
    550   ldr     r0, [ psp ]
    551   add .s  psp, psp, # 4
    552   sub .s  tos, r0, tos
    553   next,
    554 END-CODE
    555 
    556 CODE NEGATE 	\ n1 -- n2
    557 \ *G Negate an integer.
    558   rsb .s  tos, tos, # 0
    559   next,
    560 END-CODE
    561 
    562 CODE D+ 	\ d1 d2 -- d3
    563 \ *G Add two double precision integers.
    564   ldmia   psp ! { r0-r2 }		\ r0 = d2 low, r1 = d1 high, r2 = d1 low
    565   add .s  r0, r0, r2			\ d3l = d2l + d1l
    566   adc .s  tos, tos, r1			\ d3h = d2h + d1h
    567   sub .s  psp, psp, # 4
    568   str     r0, [ psp ]			\ push d3l
    569   next,
    570 END-CODE
    571 
    572 CODE D- 	\ d1 d2 -- d3
    573 \ *G Subtract two double precision integers. D3=D1-D2.
    574   ldmia   psp ! { r0-r2 }		\ r0 = d2 low, r1 = d1 high, r2 = d1 low
    575   sub .s  r0, r2, r0			\ d3l = d2l - d1l
    576   sbc .s  r1, r1, tos			\ d3h = d2h - d1h
    577   mov     tos, r1
    578   sub .s  psp, psp, # 4
    579   str     r0, [ psp ]			\ push d3l
    580   next,
    581 END-CODE
    582 
    583 CODE DNEGATE 	\ d1 -- -d1
    584 \ *G Negate a double number.
    585 L: DNEG1
    586   ldr     r0, [ psp ]			\ r0 = d1l, tos = d1h
    587   mov .s  r1, # 0
    588   rsb .s  r0, r0, # 0			\ negate low
    589   sbc .s  r1, r1, tos			\ negate high carrying through
    590   mov     tos, r1
    591   str     r0, [ psp ]
    592   next,
    593 END-CODE
    594 
    595 CODE ?NEGATE 	\ n1 flag -- n1|n2
    596 \ *G If flag is negative, then negate n1.
    597   mov .s  tos, tos			\ set processor flags
    598   ldmia   psp ! { tos }
    599   mi, if,
    600     rsb .s  tos, tos, # 0		\ negate n1 if flag=true
    601   endif,
    602   next,
    603 END-CODE
    604 
    605 ((
    606 CODE ?DNEGATE 	\ d1 flag -- d1|d2
    607   \ *G If flag is negative, then negate d1.
    608   mov .s  tos, tos			\ set processor flags
    609   ldmia   psp ! { tos }			\ discard flag
    610   b .mi   DNEG1
    611   next,
    612 END-CODE
    613 ))
    614 
    615 CODE ABS	\ n -- u
    616 \ *G If n is negative, return its positive equivalent (absolute value).
    617   cmp     tos, # 0
    618   mi, if,
    619     rsb .s  tos, tos, # 0
    620   endif,
    621   next,
    622 END-CODE
    623 
    624 CODE DABS 	\ d -- ud
    625 \ *G If d is negative, return its positive equivalent (absolute value).
    626   mov .s  tos, tos			\ set processor flags
    627   b .mi   DNEG1				\ negate d if flag=true
    628   bx      r14				\ restore link and exit
    629 END-CODE
    630 
    631 CODE D2* 	\ xd1 -- xd2
    632 \ *G Multiply the given double number by two.
    633   ldr     r0, [ psp ]			\ low portion
    634   add .s  r0, r0, r0
    635   adc .s  tos, tos, tos
    636   str     r0, [ psp ]
    637   next,
    638 END-CODE
    639 
    640 CODE D2/ 	\ xd1 -- xd2
    641 \ *G Divide the given double number by two.
    642   ldr     r0, [ psp ]			\ low portion
    643   asr .s  r0, r0, # 1			\ low portion shift right
    644   asr .s  tos, tos, # 1			\ high portion shift right
    645   sbc .s  r1, r1, r1			\ r1 -> 0/-1
    646   lsl .s  r1, r1, # #31			\ r1 -> 8/$8000:0000
    647   orr .s  r0, r0, r1			\ apply to low portion
    648   str     r0, [ psp ]
    649   next,
    650 END-CODE
    651 
    652 
    653 \ *****************
    654 \ *S Multiplication
    655 \ *****************
    656 
    657 : *		\ n1 n2 -- n3
    658 \ *G Standard signed multiply. N3 = n1 * n2.
    659   *  ;
    660 
    661 get-tos 7 =  get-psp 6 =  and [if]
    662 code UM*	\ u1 u2 -- ud
    663 \ *G Perform unsigned-multiply between two numbers and return double
    664 \ ** result.
    665   mov     r0, tos			\ r0=u2
    666   ldr     r1, [ psp, # 0 ]		\ r1=u1
    667   push    { psp }
    668 \ build result in r7:r6
    669 \ build temps in r5:r4:r3:r2
    670   lsl .s  r2, r1 # #16
    671   lsr .s  r2, r2 # #16			\ r2=u1l
    672   lsr .s  r3, r1 # #16			\ r3=u1h
    673   lsl .s  r4, r0 # 16
    674   lsr .s  r4, r4 # 16			\ r4=u2l
    675   lsr .s  r5, r0 # 16			\ r5=u2h
    676 \ scratch = r0, r1
    677 \ multiply low portions
    678   mov     r6, r2
    679   mul .s  r6, r4			\ r6=u1l*u2l
    680 \ multiply high portions
    681   mov     r7, r3
    682   mul .s  r7, r5			\ r7=u1h*u2h
    683 \ multiply and accumulate u1h * u2l
    684   mov     r0, r3
    685   mul .s  r0, r4			\ r0=u1h*u2l=xxxx.yyyy
    686   lsr .s  r1, r0 # #16			\ r1=r0h
    687   lsl .s  r0, r0 # #16			\ r1:r0=0000.xxxx:yyyy.0000
    688   add .s  r6, r6, r0			\ add into result
    689   adc .s  r7, r7, r1
    690 \ multiply and accumulate u2h * u1l
    691   mov     r0, r5
    692   mul .s  r0, r2			\ r0=u2h*u1l=xxxx.yyyy
    693   lsr .s  r1, r0 # #16			\ r1=r0h
    694   lsl .s  r0, r0 # #16			\ r1:r0=0000.xxxx:yyyy.0000
    695   add .s  r6, r6, r0			\ add into result
    696   adc .s  r7, r7, r1
    697 
    698   mov    r5, r6
    699   pop    { psp }
    700   str    r5, [ psp, # 0 ]
    701 
    702   next,
    703 end-code
    704 [then]
    705 
    706 : m*		\ n1 n2 -- d
    707 \ *G Signed multiply yielding double result.
    708   2dup xor >r				\ sign of result
    709   abs swap abs swap um*			\ process unsigned
    710   r> 0<					\ apply sign of result
    711   if  dnegate  then
    712 ;
    713 
    714 
    715 \ ***********
    716 \ *S Division
    717 \ ***********
    718 \ *P ARM Cortex-M0 provides no division instructions.
    719 
    720 code um/mod	\ ud1 u2 -- urem uquot
    721 \ *G Full 64 by 32 unsigned division subroutine.
    722   ldmia   psp ! { r0 }			\ dividend high
    723   ldr     r1, [ psp ]			\ dividend low
    724   mov .s  r4, # #32			\ loop counter
    725   mov .s  r2, # 0			\ always 0
    726   begin,
    727 \    udiv64_step
    728     add .s  r1, r1, r1			\ 64 bit shift of dividend
    729     adc .s  r0, r0, r0
    730     mov     r3, r2			\ must not affect flags
    731     adc .s  r3, r3, r2			\ preserve dividend bit 63, R2=0
    732     sub .s  r0, r0, tos			\ trial subtraction, carry set (no borrow) if ok
    733     adc .s  r3, r3, r3			\ success if bit 0 or 1 set
    734     ne, if,
    735       add .s  r1, r1, # 1		\ succeeded, update quotient
    736     else,
    737       add .s  r0, r0, tos		\ failed, undo subtraction
    738     endif,
    739     sub .s  r4, r4, # 1
    740   eq, until,
    741   mov     tos, r1			\ move quotient
    742   str     r0, [ psp ]			\ move remainder
    743   next,
    744 end-code
    745 
    746 : fm/mod	\ d n -- rem quot ; floored division
    747 \ *G Perform a signed division of double number *\i{d} by single
    748 \ ** number *\i{n} and return remainder and quotient using floored
    749 \ ** division. See the ANS Forth specification for more details
    750 \ ** of floored division.
    751   dup >r				\ sign of divisor
    752   2dup xor >r				\ sign of quotient
    753   >r					\ divisor
    754   dabs r@ abs um/mod $7FFF:FFFF and	\ unsigned divide, truncate overflow ; SFP006
    755   swap r> 0< ?negate swap		\ remainder takes sign of divisor
    756   r> 0< if				\ if quotient negative
    757     negate				\ apply sign of quotient
    758     over if				\ if remainder non-zero
    759       1-				\ decrement quotient
    760       r@ rot - swap			\ rem := divisor - rem
    761     endif
    762   endif
    763   r> drop
    764 ;
    765 
    766 : sm/rem	\ d n -- rem quot ; symmetric division
    767 \ *G Perform a signed division of double number *\i{d} by single
    768 \ ** number *\i{n} and return remainder and quotient using
    769 \ ** symmetric (normal) division.
    770   over >r                               \ save sign of dividend
    771   >r  dabs  r@ abs  um/mod              \ unsigned division
    772   r> r@ xor ?negate                     \ correct sign of quot.
    773   swap r> ?negate swap                  \ correct sign of rem.
    774 ;
    775 
    776 : /mod          \ n1 n2 -- rem quot
    777 \ *G Signed symmetric division of N1 by N2 single-precision
    778 \ ** returning remainder and quotient. Symmetric.
    779   >r s>d r> sm/rem
    780 ;
    781 
    782 : / 		\ n1 n2  -- n3
    783 \ *G Standard signed division operator. n3 = n1/n2. Symmetric.
    784   >r s>d r> sm/rem nip
    785 ;
    786 
    787 : u/ 		\ u1 u2  -- u3
    788 \ *G Unsigned division operator. u3 = u1/u2.
    789   0 swap um/mod nip
    790 ;
    791 
    792 : MOD 		\ n1 n2 -- n3
    793 \ *G Return remainder of division of N1 by N2. n3 = n1 mod n2.
    794   /mod drop  ;
    795 
    796 : M/ 		\ d n1 -- n2
    797 \ *G Signed divide of a double by a single integer.
    798   sm/rem nip  ;
    799 
    800 : MU/MOD 	\ d n -- rem d#quot
    801 \ *G Perform an unsigned divide of a double by a single, returning
    802 \ ** a single remainder and a double quotient.
    803   >r  0  r@  um/mod  r> swap >r  um/mod  r>  ;
    804 
    805 
    806 \ *********************************
    807 \ *S Scaling - multiply then divide
    808 \ *********************************
    809 \ *P These operations perform a multiply followed by a divide.
    810 \ ** The intermediate result is in an extended form.  The point
    811 \ ** of these operations is to avoid loss of precision.
    812 
    813 : */MOD 	\ n1 n2 n3 -- n4 n4
    814 \ *G Multiply n1 by n2 to give a double precision result, and then
    815 \ ** divide it by n3 returning the remainder and quotient.
    816   >r m* r> sm/rem  ;
    817 
    818 : */ 		\ n1 n2 n3 -- n4
    819 \ *G Multiply n1 by n2 to give a double precision result, and then
    820 \ ** divide it by n3 returning the quotient.
    821   */mod nip  ;
    822 
    823 ((
    824 : m*/		\ d1 n2 n3 -- dquot
    825  \ *G The result dquot=(d1*n2)/n3. The intermediate value d1*n2
    826  \ ** is triple-precision to avoid loss of precision. In an ANS
    827  \ ** Forth standard program n3 can only be a positive signed
    828  \ ** number and a negative value for n3 generates an ambiguous
    829  \ ** condition, which may cause an error on some implementations,
    830  \ ** but not in this one.
    831   s>d >r abs >r				\ -- d1 n2 ; R: -- sign(n3) |n3|
    832   s>d >r abs				\ -- d1 |n2| ; R: -- sign(n3) |n3| sign(n2)
    833   -rot					\ -- |n2| d1 ; R: -- sign(n3) |n3| sign(n2)
    834   s>d r> xor				\ -- |n2| d1 sign(d1*n2) ; R: -- sign(n3) |n3|
    835   r> swap >r >r				\ -- |n2| d1 ; R: -- sign(n3) sign(d1*n2) |n3|
    836   dabs rot				\ -- |d1| |n2| ; R: -- sign(n3) sign(d1*n2) |n3|
    837   tuck um* 2swap um*			\ -- d1h*n2 d1l*n2 ; R: -- sign(n3) sign(d1*n2) |n3|
    838   swap >r  0 d+ r> -rot			\ -- t ; R: -- sign (n3) sign(d1*n2) |n3|
    839   r@ um/mod -rot r> um/mod nip swap	\ -- d ; R: -- sign(n3) sign(d1*n2)
    840   r> r> xor IF dnegate THEN		\ -- d
    841 ;
    842 ))
    843 
    844 \ *********************
    845 \ *S Stack manipulation
    846 \ *********************
    847 
    848 : NIP 		\ x1 x2 -- x2
    849 \ *G Dispose of the second item on the data stack.
    850   nip  ;
    851 
    852 : TUCK 		\ x1 x2 -- x2 x1 x2
    853 \ *G Insert a copy of the top data stack item underneath the current
    854 \ ** second item.
    855   tuck  ;
    856 
    857 : PICK	 	\ xu .. x0 u -- xu .. x0 xu
    858 \ *G Get a copy of the Nth data stack item and place on top of stack.
    859 \ ** 0 PICK is equivalent to DUP.
    860   pick  ;
    861 
    862 CODE ROLL 	\ xu xu-1 .. x0 u -- xu-1 .. x0 xu
    863 \ *G Rotate the order of the top N stack items by one place such that
    864 \ ** the current top of stack becomes the second item and the Nth item
    865 \ ** becomes TOS. See also *\fo{ROT}.
    866   lsl .s  r0, tos # 2			\ r0=position of xu in bytes
    867   cmp     r0, # 0			\ u is valid?
    868   le, if,
    869     ldmia   psp ! { tos }		\   no - get new tos
    870     bx      link			\   no - exit
    871   endif,
    872   ldr     tos, [ psp ++ r0 ]		\ put xu in tos
    873 L: ROLL1
    874   sub .s  r1, r0, # 4
    875   ldr     r2, [ psp ++ r1 ]
    876   str     r2, [ psp ++ r0 ]
    877   mov     .s r0, r1
    878   b .ne   ROLL1
    879   add .s  psp, psp, # 4
    880   next,
    881 END-CODE
    882 
    883 : ROT 	\ x1 x2 x3 -- x2 x3 x1
    884 \ *G ROTate the positions of the top three stack items such that the
    885 \ ** current top of stack becomes the second item.
    886   rot  ;
    887 
    888 : -ROT 	\ x1 x2 x3 -- x3 x1 x2
    889 \ *G The inverse of *\fo{ROT}.
    890   -rot  ;
    891 
    892 CODE >R 	\ x -- ; R: -- x
    893 \ *G Push the current top item of the data stack onto the top of the
    894 \ ** return stack.
    895   push    { tos }
    896   ldmia   psp ! { tos }
    897   next,
    898 END-CODE
    899 
    900 CODE R> 	\ -- x ; R: x --
    901 \ *G Pop the top item from the return stack to the data stack.
    902   sub .s  psp, psp, # 4
    903   str     tos, [ psp ]
    904   pop     { tos }
    905   next,
    906 END-CODE
    907 
    908 CODE R@ 	\ --  x  ; R:  x -- x
    909 \ *G Copy the top item from the return stack to the data stack.
    910   sub .s  psp, psp, # 4
    911   str     tos, [ psp ]
    912   ldr     tos, [ rsp ]
    913   next,
    914 END-CODE
    915 
    916 CODE 2>R 	\ x1 x2 -- ; R:  -- x1 x2
    917 \ *G Transfer the two top data stack items to the return stack.
    918   ldmia   psp ! { r0, r1 }		\ r0=x1, r1=new tos
    919   push    { r0 }			\ push x1
    920   push    { tos }			\ push x2
    921   mov .s  tos, r1			\ new tos=r1
    922   next,
    923 END-CODE
    924 
    925 CODE 2R> 	\ -- x1 x2 ; R: x1 x2 --
    926 \ *G Transfer the top two return stack items to the data stack.
    927   pop     { r0 r1 }			\ r0=x2, r1=x1
    928   sub .s  psp, psp, # 8
    929   str     r1 [ psp, # 0 ]
    930   str     tos [ psp, # 4 ]
    931   mov     tos, r0			\ tos=x2
    932   next,
    933 END-CODE
    934 
    935 CODE 2R@ 	\ --  x1 x2  ; R:  x1 x2 -- x1 x2
    936 \ *G Copy the top two return stack items to the data stack.
    937   ldr     r0, [ rsp, # 0 ]		\ r0=x2
    938   ldr     r1, [ rsp, # 4 ]		\ r1=x1
    939   sub .s  psp, psp, # 8
    940   str     r1 [ psp, # 0 ]
    941   str     tos [ psp, # 4 ]
    942   mov     tos, r0                       \ tos=x2
    943   next,
    944 END-CODE
    945 
    946 : SWAP		\ x1 x2 -- x2 x1
    947 \ *G Exchange the top two data stack items.
    948   swap  ;
    949 
    950 : DUP	 	\ x -- x x
    951 \ *G DUPlicate the top stack item.
    952   dup  ;
    953 
    954 : OVER	 	\ x1 x2 -- x1 x2 x1
    955 \ *G Copy NOS to a new top-of-stack item.
    956   over  ;
    957 
    958 : DROP 		\ x --
    959 \ *G Lose the top data stack item and promote NOS to TOS.
    960   drop  ;
    961 
    962 : 2DROP 	\ x1 x2 -- )
    963 \ *G Discard the top two data stack items.
    964   2drop  ;
    965 
    966 : 2SWAP 	\ x1 x2 x3 x4 -- x3 x4 x1 x2
    967 \ *G Exchange the top two cell-pairs on the data stack.
    968   2swap  ;
    969 
    970 ((
    971 code 2ROT 	\ x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2
    972  \ *G Perform the *\fo{ROT} operation on three cell-pairs.
    973   ldmia   psp ! { r0-r4 }		\ tos=x6, r0=x5, r4=x1
    974   sub .s  psp, psp, # 5 cells		\ restore stack depth
    975   str     r4, [ psp, # 0 cells ]	\ x1
    976   str     tos [ psp, # 1 cells ]	\ x6
    977   str     r0, [ psp, # 2 cells ]	\ x5
    978   str     r1, [ psp, # 3 cells ]	\ x4
    979   str     r2, [ psp, # 4 cells ]	\ x3
    980   mov     tos, r3			\ x2 to tos
    981   next,
    982 END-CODE
    983 ))
    984 
    985 : 2DUP		\ x1 x2 -- x1 x2 x1 x2
    986 \ *G DUPlicate the top cell-pair on the data stack.
    987   2dup  ;
    988 
    989 : 2OVER 	\ x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2
    990 \ *G As *\fo{OVER} but works with cell-pairs rather than single-cell items.
    991   2over  ;
    992 
    993 : ?DUP		\ x -- | x
    994 \ *G DUPlicate the top stack item only if it non-zero.
    995   ?dup  ;
    996 
    997 CODE SP@ 	\ -- x
    998 \ *G Get the current address value of the data-stack pointer.
    999   sub .s  psp, psp, # 4
   1000   str     tos, [ psp ]
   1001   mov     tos, psp
   1002   next,
   1003 END-CODE
   1004 
   1005 CODE SP! 	\ x --
   1006 \ *G Set the current address value of the data-stack pointer.
   1007   mov     psp, tos
   1008   ldmia   psp ! { tos }
   1009   next,
   1010 END-CODE
   1011 
   1012 CODE RP@ 	\ -- x
   1013 \ *G Get the current address value of the return-stack pointer.
   1014   sub .s  psp, psp, # 4
   1015   str     tos, [ psp ]
   1016   mov     tos, rsp
   1017   next,
   1018 END-CODE
   1019 
   1020 CODE RP! 	\ x --
   1021 \ *G Set the current address value of the return-stack pointer.
   1022   mov     rsp, tos
   1023   ldmia   psp ! { tos }
   1024   next,
   1025 END-CODE
   1026 
   1027 ((
   1028 CODE >RR 	\ x -- ; R: -- x
   1029  \ *G Push the current top item of the data stack onto the top of the
   1030  \ ** return stack as a return address
   1031   mov .s  r0, # 1			\ set the T bit
   1032   orr .s  tos, tos, r0
   1033   push    { tos }
   1034   ldmia   psp ! { tos }
   1035   next,
   1036 END-CODE
   1037 
   1038 CODE RR> 	\ -- x ; R: x --
   1039  \ *G Pop the caller's return address from the return stack.
   1040   sub .s  psp, psp, # 4
   1041   str     tos, [ psp ]
   1042   pop     { tos }
   1043   mov .s  r0, # 1			\ clear the T bit
   1044   bic .s  tos, tos, r0
   1045   next,
   1046 END-CODE
   1047 
   1048 CODE RR@ 	\ --  x  ; R:  x -- x
   1049  \ *G Copy the top item from the return stack to the data stack.
   1050   sub .s  psp, psp, # 4
   1051   str     tos, [ psp ]
   1052   ldr     tos, [ rsp ]
   1053   mov .s  r0, # 1			\ clear the T bit
   1054   bic .s  tos, tos, r0
   1055   next,
   1056 END-CODE
   1057 ))
   1058 
   1059 
   1060 \ ******************************
   1061 \ *S String and memory operators
   1062 \ ******************************
   1063 
   1064 : COUNT 	\ c-addr1 -- c-addr2' u
   1065 \ *G Given the address of a counted string in memory this word will
   1066 \ ** return the address of the first character and the length in
   1067 \ ** characters of the string.
   1068   count  ;
   1069 
   1070 : /STRING 	\ c-addr1 u1 n -- c-addr2 u2
   1071 \ *G Modify a string address and length to remove the first N characters
   1072 \ ** from the string.
   1073   /string  ;
   1074 
   1075 CODE SKIP 	\ c-addr1 u1 char -- c-addr2 u2
   1076 \ *G Modify the string description by skipping over leading occurrences of
   1077 \ ** 'char'.
   1078   ldmia   psp ! { r0, r1 }		\ tos=char, r0=len, r1=adr1
   1079   add .s  r0, r0, # 1
   1080 L: SK1
   1081   sub .s  r0, r0, # 1
   1082   b .eq   SKIPDONE
   1083   ldrb    r2, [ r1 ]
   1084   cmp     r2, tos
   1085   eq, if,
   1086     add .s  r1, r1, # 1
   1087     b       SK1
   1088   endif,
   1089 L: SKIPDONE
   1090   sub .s  psp, psp, # 4
   1091   str     r1, [ psp ]			\ push c-addr2
   1092   mov     tos, r0			\ u2
   1093   next,
   1094 END-CODE
   1095 
   1096 CODE SCAN 	\ c-addr1 u1 char -- c-addr2 u2
   1097 \ *G Look for first occurrence of *\i{char} in the string and
   1098 \ ** return a new string. *\i{C-addr2/u2} describes the string
   1099 \ ** with *\i{char} as the first character.
   1100   ldmia   psp ! { r0, r1 }		\ tos=char, r0=len, r1=adr1
   1101   add .s  r0, r0, # 1
   1102 L: SC1
   1103   sub .s  r0, r0, # 1
   1104   b .eq   SCANDONE
   1105   ldrb    r2, [ r1 ]
   1106   cmp r2, tos
   1107   ne, if,
   1108     add .s  r1, r1, # 1
   1109     b       SC1
   1110   endif,
   1111 L: SCANDONE
   1112   sub .s  psp, psp, # 4
   1113   str     r1, [ psp ]			\ push c-addr2
   1114   mov     tos, r0			\ u2
   1115   next,
   1116 END-CODE
   1117 
   1118 CODE S=		\ c-addr1 c-addr2 u -- flag
   1119 \ *G Compare two same-length strings/memory blocks, returning TRUE if
   1120 \ ** they are identical.
   1121   ldmia   psp ! { r0, r1 }		\ r0=adr2, r1=adr1
   1122   mov .s  tos, tos
   1123   b .eq   S=X                           \ TRUE as len=0
   1124 L: S=1
   1125   ldrb    r2, [ r0 ]
   1126   ldrb    r3, [ r1 ]
   1127   add .s  r0, r0, # 1
   1128   add .s  r1, r1, # 1
   1129   cmp     r2, r3
   1130   b .ne   S=X                           \ FALSE as mismatched chars
   1131   sub .s  tos, tos, # 1
   1132   b .ne   S=1                           \ if count=0 then TRUE
   1133 L: S=X
   1134   eq, if,
   1135     mov .s  tos, # 1
   1136     neg .s  tos, tos			\ TRUE
   1137   else,
   1138     mov .s  tos, # 0			\ FALSE
   1139   then,
   1140   next,
   1141 END-CODE
   1142 
   1143 : compare       \ c-addr1 u1 c-addr2 u2 -- n                    17.6.1.0935
   1144 \ *G Compare two strings. The return result is 0 for a match or can be
   1145 \ ** -ve/+ve indicating string differences.
   1146 \ ** If the two strings are identical, n is zero. If the two strings
   1147 \ ** are identical up to the length of the shorter string, n is
   1148 \ ** minus-one (-1) if u1 is less than u2 and one (1) otherwise.
   1149 \ ** If the two strings are not identical up to the length of the
   1150 \ ** shorter string, n is minus-one (-1) if the first non-matching
   1151 \ ** character in the string specified by c-addr1 u1 has a lesser
   1152 \ ** numeric value than the corresponding character in the string
   1153 \ ** specified by c-addr2 u2 and one (1) otherwise.
   1154   rot swap                      \ c-addr1 c-addr2 u1 u2
   1155   2dup - >r min                 \ c-addr1 c-addr2 minlen -- R: lendiff? --
   1156 
   1157   begin
   1158     dup
   1159   while
   1160     -rot over c@ over c@ -	\ length c-addr1 c-addr2 (char1-char2)
   1161     dup if			\ If chars are different
   1162       r> drop >r		\  replace lendiff result with error code
   1163       drop 0			\  and put 0 on TOS (make len==0 at BEGIN)
   1164     else                        \ otherwise
   1165       drop			\  discard difference
   1166       1+ swap 1+ swap  rot 1-	\  increment addresses and decrement length
   1167     then
   1168   repeat
   1169   drop 2drop                    \ remove addresses and null count from stack
   1170                                 \ -- ; R: result --
   1171   r> dup if 0< 1 or then        \ make nice flag, 0 becomes 0, -ve becomes -1
   1172                                 \            and  +ve becomes 1
   1173 ;
   1174 
   1175 internal
   1176 : (search)	{ c-addr1 u1 c-addr2 u2 -- c-addr3 u3 flag }
   1177   c-addr1 u1 u2 - 1+ bounds     	\ Search for first char of $2 in $1.  Note that
   1178   ?do                           	\ we only check LEN($1)-LEN($2)+1 chars of $1.
   1179     i c@  c-addr2 c@  = if        	\ Compare next char of $1 with first char of $2.
   1180       i c-addr2 u2 s= if           	\ Is the whole of $2 present?
   1181         i u1 i c-addr1 - - true 	\ Yes - build return stack parameters...
   1182         unloop exit             	\ ...and bail out.
   1183       then
   1184     then
   1185   loop
   1186   c-addr1 u1 false            		\ End of loop and first char not found - no match.
   1187 ;
   1188 external
   1189 
   1190 : SEARCH	( c-addr1 u1 c-addr2 u2 -- c-addr3 u3 flag  )
   1191 \ *G Search the string c-addr1/u1 for the string c-addr2/u2. If a match
   1192 \ ** is found return c-addr3/u3, the address of the start of the match
   1193 \ ** and the number of characters remaining in c-addr1/u1, plus flag f
   1194 \ ** set to true. If no match was found return c-addr1/u1 and f=0.
   1195   2 pick over <         		\ Is $1 shorter than $2?
   1196   if  2drop false exit  then   		\ Yes - $2 *can't* be in $1.
   1197   dup 0 <=              		\ Is $2 zero length?
   1198   if  2drop true exit  then    		\ Yes - we have found it at the start of $1.
   1199   2 pick 0 <=           		\ Is $1 zero length?
   1200   if  2drop false exit  then   		\ Yes - string not found.
   1201   (search)
   1202 ;
   1203 
   1204 code cmove	\ asrc adest len --
   1205 \ *G Copy *\i{len} bytes of memory forwards from *\i{asrc} to *\i{adest}.
   1206   mov .s  r3, tos                	\ r3=len
   1207   ldmia   psp ! { r0, r1, tos }		\ r0=addr2, r1=addr1, r3=len, tos restored
   1208   eq, if,
   1209     bx      link			\ return if len=0, nothing to do
   1210   endif,
   1211   mov .s  r2, r0
   1212   orr .s  r2, r2, r1			\ check alignment
   1213   orr .s  r2, r2, r3			\ R2 := adr1|addr2|len
   1214   mov .s  r4, # 3
   1215   and .s  r4, r4, r2,			\ will be zero if aligned
   1216   b .ne   cmovx3			\ if not aligned
   1217 L: CMOVX1
   1218   ldr     r2, [ r1 ]
   1219   str     r2, [ r0 ]
   1220   add .s  r1, r1, # 4
   1221   add .s  r0, r0, # 4
   1222   sub .s  r3, r3, # 4
   1223   b .ne   CMOVX1
   1224   next,
   1225 L: CMOVX3
   1226   ldrb    r2, [ r1 ]
   1227   strb    r2, [ r0 ]
   1228   add .s  r1, r1, # 1
   1229   add .s  r0, r0, # 1
   1230   sub .s  r3, r3, # 1
   1231   b .ne   CMOVX3
   1232   next,
   1233 END-CODE
   1234 
   1235 CODE CMOVE>	\ c-addr1 c-addr2 u --
   1236 \ *G As *\fo{CMOVE} but working in the opposite direction,
   1237 \ ** copying the last character in the string first.
   1238   mov .s  r3, tos                	\ r3=len
   1239   ldmia   psp ! { r0, r1, tos }		\ r0=addr2, r1=addr1, r3=len, tos restored
   1240   eq, if,
   1241     bx      link			\ return if len=0, nothing to do
   1242   endif,
   1243   add .s  r0, r0, r3			\ addr2+len
   1244   add .s  r1, r1, r3			\ addr1+len
   1245   mov .s  r2, r0
   1246   orr .s  r2, r2, r1			\ check alignment
   1247   orr .s  r2, r2, r3			\ R2 := adr1|addr2|len
   1248   mov .s  r4, # 3
   1249   and .s  r4, r4, r2,			\ will be zero if aligned
   1250   b .ne   CMV>3				\ byte by byte if not aligned
   1251 L: CMV>1	\ copy by 4 byte units
   1252   sub .s  r1, r1, # 4
   1253   sub .s  r0, r0, # 4
   1254   ldr     r2, [ r1 ]
   1255   str     r2, [ r0 ]
   1256   sub .s  r3, r3, # 4
   1257   b .ne   CMV>1
   1258   next,
   1259 L: CMV>3	\ copy byte by byte
   1260   sub .s  r1, r1, # 1
   1261   sub .s  r0, r0, # 1
   1262   ldrb    r2, [ r1 ]
   1263   strb    r2, [ r0 ]
   1264   sub .s  r3, r3, # 1
   1265   b .ne   CMV>3
   1266   next,
   1267 END-CODE
   1268 
   1269 : upc		\ char -- char' ; force upper case
   1270 \ *G Convert char to upper case.
   1271   dup [char] a >= if
   1272     dup [char] z <= if
   1273       $DF and
   1274     endif
   1275   endif
   1276 ;
   1277 
   1278 : upper		\ c-addr len --
   1279 \ *G Convert the ASCII string described to upper-case. This operation
   1280 \ ** happens in place.
   1281   bounds ?do  i c@ upc i c!  loop
   1282 ;
   1283 
   1284 : PLACE         \ c-addr1 u c-addr2 --
   1285 \ *G Place the string c-addr1/u as a counted string at c-addr2.
   1286   2dup 2>r  1+ swap move  2r> c!
   1287 ;
   1288 
   1289 : ON		\ a-addr --
   1290 \ *G Given the address of a CELL this will set its contents to TRUE (-1).
   1291   on  ;
   1292 
   1293 : OFF	 	\ a-addr --
   1294 \ *G Given the address of a CELL this will set its contents to FALSE (0).
   1295   off  ;
   1296 
   1297 ((
   1298 CODE C+!	\ b c-addr --
   1299  \ *G Add N to the character (byte) at memory address ADDR.
   1300   ldmia   psp ! { r0 }
   1301   ldrb    r1, [ tos ]
   1302   add .s  r1, r1, r0
   1303   strb    r1, [ tos ]
   1304   ldmia   psp ! { tos }
   1305   next,
   1306 END-CODE
   1307 ))
   1308 
   1309 CODE 2@		\ a-addr -- x1 x2
   1310 \ *G Fetch and return the two CELLS from memory ADDR and ADDR+sizeof(CELL).
   1311 \ ** The cell at the lower address is on the top of the stack.
   1312   ldmia   tos ! { r0 r1 }		\ r0 from low address
   1313   sub .s  psp, psp, # 4
   1314   mov     tos, r0
   1315   str     r1, [ psp ]
   1316   next,
   1317 END-CODE
   1318 
   1319 CODE 2! 	\ x1 x2 a-addr --
   1320 \ *G Store the two CELLS x1 and x2 at memory ADDR.
   1321 \ ** X2 is stored at ADDR and X1 is stored at ADDR+CELL.
   1322   mov .s  r2, tos
   1323   ldmia   psp ! { r0, r1, tos }		\ r0=x2, r1=x1
   1324   stmia  r2 ! { r0 r1 }
   1325   next,
   1326 END-CODE
   1327 
   1328 CODE FILL	\ c-addr u char --
   1329 \ *G Fill LEN bytes of memory starting at ADDR with the byte information
   1330 \ ** specified as CHAR.
   1331   mov .s  r2, tos
   1332   ldmia   psp ! { r0, r1, tos }		\ r2=char, r0=count, r1=addr
   1333   cmp     r0, # 0
   1334   b .eq   FILX
   1335 L: FIL1
   1336   strb    r2, [ r1 ]
   1337   add .s  r1, r1, # 1
   1338   sub .s  r0, r0, # 1
   1339   b .ne FIL1
   1340 L: FILX
   1341   next,
   1342 END-CODE
   1343 
   1344 : +!		\ n|u a-addr --
   1345 \ *G Add N to the CELL at memory address ADDR.
   1346   +!  ;
   1347 
   1348 : INCR	 	\ a-addr --
   1349 \ *G Increment the data cell at a-addr by one.
   1350   incr  ;
   1351 
   1352 : DECR		\ a-addr --
   1353 \ *G Decrement the data cell at a-addr by one.
   1354   decr  ;
   1355 
   1356 : @		\ a-addr -- x
   1357 \ *G Fetch and return the CELL at memory ADDR.
   1358   @  ;
   1359 
   1360 : W@	 	\ a-addr -- w
   1361 \ *G Fetch and 0 extend the word (16 bit) at memory ADDR.
   1362   w@  ;
   1363 
   1364 : C@	 	\ c-addr -- char
   1365 \ *G Fetch and 0 extend the character at memory ADDR and return.
   1366   c@  ;
   1367 
   1368 : ! 		\ x a-addr --
   1369 \ *G Store the CELL quantity X at memory A-ADDR.
   1370   !  ;
   1371 
   1372 : W!	 	\ w a-addr --
   1373 \ *G Store the word (16 bit) quantity w at memory ADDR.
   1374   w!  ;
   1375 
   1376 : C!	 	\ char c-addr --
   1377 \ *G Store the character CHAR at memory C-ADDR.
   1378   c!  ;
   1379 
   1380 : TEST-BIT	\ mask c-addr -- flag
   1381 \ *G AND the mask with the contents of addr and return the result.
   1382   c@ and  ;
   1383 
   1384 : SET-BIT	\ mask c-addr --
   1385 \ *G Apply the mask ORred with the contents of c-addr.
   1386 \ ** Byte operation.
   1387   bor!  ;
   1388 
   1389 : RESET-BIT	\ mask c-addr --
   1390 \ *G Apply the mask inverted and ANDed with the contents of c-addr.
   1391 \ ** Byte operation.
   1392   bbic!  ;
   1393 
   1394 ((
   1395 CODE TOGGLE-BIT	\ u c-addr --
   1396  \ *G Invert the bits at c-addr specified by the mask. Byte operation.
   1397   ldmia   psp ! { r0 }			\ get mask
   1398   ldrb    r1, [ tos ]			\ get byte from addr
   1399   eor .s  r1, r1, r0			\ apply mask
   1400   strb    r1, [ tos ]			\ store byte
   1401   ldmia  psp ! { tos }			\ get new tos
   1402   next,
   1403 END-CODE
   1404 ))
   1405 
   1406 
   1407 \ **********************
   1408 \ *S Miscellaneous words
   1409 \ **********************
   1410 
   1411 : NAME>	\ nfa -- cfa
   1412 \ *G Move a pointer from an NFA to the XT..
   1413   dup c@ $1F and + 4 + -4 and  ;		\ 1 for count byte, 3 for aligning
   1414 
   1415 \ On Cortex, name field is a multiple of 4 bytes so we only need to
   1416 \ check top bit of every fourth byte when working back from the cfa
   1417 \ to find the nfa
   1418 : >NAME	\ cfa -- nfa
   1419 \ *G Move a pointer from an XT back to the NFA or name-pointer.
   1420 \ ** If the original pointer was not an XT or if the definition
   1421 \ ** in question has no name header in the dictionary the
   1422 \ ** returned pointer will be useless. Care should be taken when
   1423 \ ** manipulating or scanning the Forth dictionary in this way.
   1424   begin  4 - dup @ $80 and  until	\ nfa in low byte
   1425 ;
   1426 
   1427 internal
   1428 : (SEARCH-WORDLIST)     ( c-addr u ^^nfa -- 0 | xt 1 | xt -1 )
   1429   begin
   1430     @ dup
   1431   while
   1432     dup c@ $1F and			\ -- c-addr u ^nfa nfalen ;
   1433     2 pick = if				\ Are the names the same *length*?
   1434       dup 1+ 3 pick 3 pick s= if	\ Are they the same *name*?
   1435         nip nip
   1436         dup name> swap
   1437         c@ $40 and ( 0= )		\ check for immediacy (0=immediate)
   1438         if  -1  else  1  then
   1439         exit
   1440       then
   1441     then
   1442     ( n>link ) cell -
   1443   repeat
   1444   drop 2drop 0
   1445 ;
   1446 
   1447 : SEARCH-WORDLIST	\ c-addr u wid -- 0|xt 1|xt -1
   1448 \ *G Search the given wordlist for a definition. If the definition is
   1449 \ ** not found then 0 is returned, otherwise the XT of the definition
   1450 \ ** is returned along with a non-zero code. A -ve code indicates a
   1451 \ ** "normal" definition and a +ve code indicates an *\fo{IMMEDIATE} word.
   1452   dup 0= if
   1453     nip nip
   1454   else					\ -- c-addr u wid
   1455     over 3 pick c@ + over @ 1- and      \ -- c-addr u wid thread#
   1456     1+ cells +                          \ -- c-addr u ^nfa
   1457     (search-wordlist)
   1458   then
   1459 ;
   1460 
   1461 CODE DIGIT 	\ char n -- 0|n true
   1462 \ *G If the ASCII value *\i{CHAR} can be treated as a digit for a number
   1463 \ ** within the radix *\i{N} then return the digit and a TRUE flag, otherwise
   1464 \ ** return FALSE.
   1465   ldmia   psp ! { r0 }			\ base in tos, char in r0
   1466   sub .s  r0, r0, # $30                 \ '0'
   1467   b .mi   DIG2				\ fail if char < '0'
   1468   cmp     r0, # $0A
   1469   b .lt   DIG1				\ true, '0' <= char <= '9@
   1470   sub .s  r0, r0, # 7			\ convert 'A'..'F'
   1471   cmp     r0, # $0A
   1472   b .lt   DIG2				\ fail if result < 'A'
   1473 L: DIG1
   1474   cmp     r0, tos			\ in range of base?
   1475   lt, if,
   1476     mov .s  tos, # 1			\ yes, tos=true
   1477     neg .s  tos, tos
   1478     sub .s  psp, psp, # 4
   1479     str     r0, [ psp ]			\ push n
   1480     next,
   1481   endif,				\ exit
   1482 L: DIG2
   1483   mov .s  tos, # 0                      \ tos=false
   1484   next,                                 \ exit
   1485 END-CODE
   1486 
   1487 
   1488 \ **********************
   1489 \ *S Portability helpers
   1490 \ **********************
   1491 \ *P Using these words will make code easier to port between
   1492 \ ** 16, 32 and 64 bit targets.
   1493 
   1494 CODE CELL+ 	\ a-addr1 -- a-addr2
   1495 \ *G Add the size of a CELL to the top-of stack.
   1496   add .s  tos, tos, # 4
   1497   next,
   1498 END-CODE
   1499 
   1500 CODE CELLS 	\ n1 -- n2
   1501 \ *G Return the size in address units of N1 cells in memory.
   1502   mov .s  tos, tos .lsl # 2
   1503   next,
   1504 END-CODE
   1505 
   1506 CODE CELL- 	\ a-addr1 -- a-addr2
   1507 \ *G Decrement an address by the size of a cell.
   1508   sub .s  tos, tos, # 4
   1509   next,
   1510 END-CODE
   1511 
   1512 CODE CELL 	\ -- n
   1513 \ *G Return the size in address units of one CELL.
   1514   sub .s  psp, psp, # 4
   1515   str     tos, [ psp ]		 	\ save TOS
   1516   mov .s  tos, # 4	             	\ return cell size
   1517   next,
   1518 END-CODE
   1519 
   1520 ((
   1521 CODE CHAR+ 	\ c-addr1 -- c-addr2
   1522 \ *G Increment an address by the size of a character.
   1523   add .s  tos, tos, # 1
   1524   next,
   1525 END-CODE
   1526 
   1527 : CHARS 	\ n1 -- n2
   1528 \ *G Return size in address units of N1 characters.
   1529 ; immediate
   1530 ))
   1531 
   1532 
   1533 \ **************************************
   1534 \ *S Supporting complation on the target
   1535 \ **************************************
   1536 \ *P Compilation on the target is supported for compilation into
   1537 \ ** Flash. The target's compiler is simplistic and gives neither
   1538 \ ** the code size nor the performance of cross-compiled code.
   1539 \ ** The support words are compiled without heads.
   1540 
   1541 interpreter also asm-access		\ black magic here!
   1542   get-rsp  get-psp  get-tos
   1543 previous target
   1544 equ tos-reg  equ psp-reg  equ rsp-reg
   1545 
   1546 internal
   1547 : opc32,	\ opc32 -- ; compile 32 bit opcode
   1548   dup #16 rshift w, w,  ;
   1549 
   1550 : opc32!	\ opc32 addr -- ; store a 32 bit opcode
   1551   over #16 rshift over w!f  2 + w!f  ;
   1552 
   1553 ((
   1554 : opc32@	\ addr -- opc32 ; fetch a 32 bit opcode
   1555   dup w@ #16 lshift  swap 2 + w@ or  ;
   1556 ))
   1557 
   1558 ((
   1559 \ Short form for calls
   1560   bl      <dest>			\ $+00
   1561   ...					\ $+04, returns here
   1562 \ Long form for calls, start is NOT aligned
   1563   ldr    r0, $ 6 +			\ $+00
   1564   blx    r0				\ $+02
   1565   b      $ 6 +				\ $+04  skip address
   1566   addr					\ $+06  location must be aligned
   1567 ))
   1568 
   1569 ((
   1570 : inRange24?	\ dest -- flag ; true if +/-24 bit
   1571   here 4 + - $FF00:0000 $00FF:FFFE within?  ;
   1572 ))
   1573 
   1574 : GenJ		\ offset mask -- Jx ; J := (notI) xor S
   1575   over and 0=  swap 0< xor  ;
   1576 
   1577 : CalcTrel24	\ dest orig -- field24
   1578 \ calculate field for 24 bit Thumb branch
   1579   4 + -  1 arshift			\ half word align
   1580   dup $7FF and 				\ offset imm11 ;    bits 10..0  -> 10..0
   1581   over #11 rshift $3FF and #16 lshift or \ merge imm10 ;     bits 20..11 -> 25..16
   1582   over $0020:0000 GenJ $0000:2000 and or \ merge J1/bit13 ; I1=bit21    -> 13
   1583   over $0040:0000 GenJ $0000:0800 and or \ merge J2/bit11 ; I2=bit22    -> 11
   1584   swap 0< $0400:0000 and or		\ merge S to bit26
   1585 ;
   1586 
   1587 : bl24		\ dest orig -- opc
   1588   calcTrel24 $F000:D000 or  ;
   1589 
   1590 : pushLR.n,	\ -- ; lay 16 bit push of LR to return stack
   1591   $B500 w,  ;				\ push { lr }
   1592 
   1593 : nop.n,	\ -- ; lay 16 bit NOP
   1594   $BF00 w, ;				\ nop .n
   1595 
   1596 : !scall	\ dest addr --
   1597 \ +G Patch a BL DEST opcode at addr.
   1598   tuck  bl24  swap opc32!  ;
   1599 
   1600 $1E00 4 6 lshift or psp-reg 3 lshift or psp-reg or equ subPspIns
   1601 \ Instruction opcode for SUB  psp, psp, # 4
   1602 $6000 psp-reg 3 lshift or tos-reg or equ strTosIns
   1603 \ Instruction opcode for STR  tos, [ psp # 0 ]
   1604 
   1605 : saveTos,	\ -- ; compiles push of tos to data stack
   1606   subPspIns w,				\ sub  psp, psp, # 4
   1607   strTosIns w,				\ template for str rt, [ rn, # 0 ]
   1608 ;
   1609 
   1610 : dataPtr@,	\ -- ; compiles fetch to TOS through LR
   1611   $4670 w,				\ mov     r0, link
   1612   $1E40 w,				\ sub .s  r0, r0, # 1
   1613   $6800 tos-reg or w,			\ ldr     tos, [ r0, # 0 ]
   1614 ;
   1615 
   1616 : scall,	\ addr --
   1617 \ +G Compile a machine code BL to addr. No range checking is performed.
   1618   here bl24 opc32,  ;
   1619 
   1620 : compileAligned,	\ xt --
   1621   here 2 and
   1622   if  nop.n,  endif
   1623   scall,
   1624 ;
   1625 
   1626 : DOCOLON, 	\ --
   1627 \ +G Compile the runtime entry code required by colon definitions.
   1628 \ +* INTERNAL.
   1629   pushLR.n,  ;				\ push { r14 }
   1630 
   1631 CODE LIT 	\ -- x
   1632 \ *G Code which when CALLED at runtime will return an inline cell
   1633 \ ** value. The call must be at a four byte boundary. INTERNAL.
   1634   sub .s  psp, psp, # 4			\ save TOS
   1635   str     tos, [ psp, # 0 ]
   1636   mov     r0, link			\ LINK is high register
   1637   sub .s  r0, r0, # 1			\ remove T bit
   1638   ldr     tos, [ r0, # 0 ]		\ get data (in-line)
   1639   add .s  r0, r0, # 5			\ restore T bit, step over data
   1640   bx      r0
   1641 END-CODE
   1642 
   1643 CODE (") 	\ -- a-addr ; return address of string, skip over it
   1644 \ *G Return the address of a counted string that is inline after the
   1645 \ ** CALLING word, and adjust the CALLING word's return address to
   1646 \ ** step over the inline string. The adjusted return address will
   1647 \ ** be at a four byte boundary.
   1648 \ ** See the definition of *\fo{(.")} for an example.
   1649   sub .s  psp, psp, # 4			\ save TOS
   1650   str     tos, [ psp, # 0 ]
   1651   ldr     tos, [ rsp, # 0 ]		\ get return address of CALLER
   1652   sub .s  tos, tos, # 1			\ remove Thumb bit
   1653   ldrb    r1, [ tos, # 0 ]		\ length byte
   1654   add .s  r1, r1, tos			\ r1=address+length
   1655   add .s  r1, r1, # 4			\ +1 for count byte, +3 to align
   1656   mov .s  r2, # 3			\ -4 AND -> 3 BIC
   1657   bic .s  r1, r1, r2
   1658   add .s  r1, r1, # 1			\ restore Thumb bit
   1659   str     r1, [ rsp, # 0 ]		\ update return address
   1660   next,
   1661 END-CODE
   1662 
   1663 external
   1664 
   1665 
   1666 \ *************************************
   1667 \ *S Defining words and runtime support
   1668 \ *************************************
   1669 
   1670 : aligned       \ addr -- addr'
   1671 \ *G Given an address pointer this word will return the next ALIGNED
   1672 \ ** address subject to system wide alignment restrictions.
   1673   3 + -4 and
   1674 ;
   1675 compiler
   1676 : aligned       \ addr -- addr'
   1677   3 + -4 and
   1678 ;
   1679 target
   1680 
   1681 
   1682 ASMCODE
   1683 align L: DOCREATE	\ -- addr
   1684 \ +G The run time action of *\fo{CREATE}. The call must be on a
   1685 \ +* four byte boundary. INTERNAL.
   1686   sub .s  psp, psp, # 4			\ save TOS
   1687   str     tos, [ psp, # 0 ]
   1688   mov     r0, link			\ LINK is high register
   1689   sub .s  r0, r0, # 1			\ remove T bit
   1690   ldr     tos, [ r0, # 0 ]		\ get data address (in-line)
   1691   pop     { pc }
   1692 end-code
   1693 
   1694 : compile,	\ xt --
   1695 \ *G Compile the word specified by xt into the current definition.
   1696   scall,  ;
   1697 
   1698 : >BODY		\ xt -- a-addr
   1699 \ *G Move a pointer from a CFA or "XT" to the definition's data
   1700 \ ** area. *\fo{>BODY} should only be used with children of
   1701 \ ** *\fo{CREATE}. If *\fo{FOOBAR} is defined with *\fo{CREATE foobar},
   1702 \ ** then the phrase *\fo{' FOOBAR >BODY} would give the same
   1703 \ ** result as executing *\fo{FOOBAR}.
   1704   8 + @  ;
   1705 
   1706 internal
   1707 : (docreate,) 	\ --
   1708   nop.n,  pushLR.n,  DOCREATE scall,
   1709 ;
   1710 
   1711 : (dobuild,)	\ -- ; lay dummy cfa
   1712   nop.n,  pushLR.n,  4 allot		\ lay down m/c call for later patching
   1713 \  nop.n,  pushLR.n,  $F7FF:FFFF , 	\ lay down m/c call for later patching
   1714 ;
   1715 
   1716 : namedBuild,	\ val --
   1717 \ +G Start a target defining word.
   1718   [ROM  header, (dobuild,) swap ,  ROM]
   1719 ;
   1720 
   1721 : (;CODE) 	\ -- ; R: a-addr --
   1722 \ *G Performed at compile time by *\fo{;CODE} and *\fo{DOES>}.
   1723 \ ** Patch the last word defined (by *\fo{CREATE}) to have the
   1724 \ ** run time actions that follow immediately after *\fo{(;CODE)}.
   1725 \ ** INTERNAL.
   1726   r> -2 and  latest name> 4 + !scall  ;	\ SFP004
   1727 
   1728 variable immheader	 \ -- addr
   1729 external
   1730 
   1731 : Imm		\ --
   1732 \ *G Used before a definition to indicate that it is *\fo{IMMEDIATE},
   1733 \ ** which means that it will execute whenever encountered regardless
   1734 \ ** of whether the system is compiling.
   1735   immheader on
   1736 ;
   1737 
   1738 target-only
   1739 : :		\ C: "<spaces>name" -- colon-sys ; Exec: i*x -- j*x ; R: -- nest-sys
   1740 \ *G Begin a new definition called *\fo{name}.
   1741   ?EXEC !CSP  header,  hide  ]  docolon,
   1742 ; immediate
   1743 host&target
   1744 
   1745 target-only
   1746 : :NONAME	\ C: -- colon-sys ; Exec: i*x -- i*x  ; R: -- nest-sys
   1747 \ *G Begin a new code definition which does not have a name. After the
   1748 \ ** definition is complete the semi-colon operator returns the XT of
   1749 \ ** newly compiled code on the stack.
   1750   !csp                                  \ compiler stack security
   1751   align  here last !  0 ,		\ lay null header to fool SMUDGE
   1752   here  ] docolon,			\ compiler on, lay entry code
   1753 ;
   1754 host&target
   1755 
   1756 : DOES>		\ C: colon-sys1 -- colon-sys2 ; Run: -- ; R:  nest-sys --
   1757 \ *G Begin definition of the runtime-action of a child of a defining word.
   1758 \ ** See the section about defining words in *\i{Programming Forth}.
   1759 \ ** You should not use *\fo{RECURSE} after *\fo{DOES>}.
   1760 cr ." DOES>"
   1761   ['] (;code) compile,
   1762 cr ." a"
   1763   saveTos,
   1764 cr ." b"
   1765   dataPtr@,
   1766 cr ." c"
   1767 ;
   1768 IMMEDIATE
   1769 
   1770 : CREATE        \ --
   1771 \ *G Create a new definition in the dictionary. When the new
   1772 \ ** definition is executed it will return the address of the
   1773 \ ** definition's data area. As compilation is into Flash,
   1774 \ ** *\fo{CREATE} cannot be used with *\fo{DOES>} and
   1775 \ ** *\fo{ <BUILDS ... DOES> ...} must be used instead.
   1776   ROM? [ROM swap			\ old flag
   1777   header, (docreate,) dataAddr,		\ header, m/c call, address
   1778   ROM]
   1779 ;
   1780 
   1781 : <BUILDS	\ --
   1782 \ *G Always used in the form:
   1783 \ *C  : defword <BUILDS ... DOES> ... ;
   1784 \ *P When *\fo{defword} is executed a new definition is created
   1785 \ ** with the data defined between *\fo{<BUILDS} and *\fo{DOES>}
   1786 \ ** and the action defined between *\fo{DOES>} and *\fo{;}.
   1787 \ ** You must use *\fo{<BUILDS} and *\fo{DOES>} together, otherwise
   1788 \ ** there will be a crash. Treat *\fo{<BUILDS} as a special case
   1789 \ ** of *\fo{CREATE} for use with *\fo{DOES>} and compilation into
   1790 \ ** Flash.
   1791   ROM? [ROM swap			\ old flag
   1792   header, (dobuild,) dataAddr,		\ header, m/c call, address
   1793   ROM]
   1794 ;
   1795 
   1796 : CONSTANT 	\ x "<spaces>name" -- ; Exec: -- x
   1797 \ *G Create a new *\fo{CONSTANT} called *\fo{name} which has the
   1798 \ ** value *\i{x}. When *\fo{NAME} is executed *\i{x} is returned.
   1799   namedBuild,  ;CODE
   1800   sub .s  psp, psp, # 4			\ save TOS
   1801   str     tos, [ psp, # 0 ]
   1802   mov     r0, link			\ LINK is high register
   1803   sub .s  r0, r0, # 1			\ remove T bit
   1804   ldr     tos, [ r0, # 0 ]		\ get data address (in-line)
   1805   pop     { pc }
   1806 END-CODE
   1807 
   1808 : 2CONSTANT	\ Comp: x1 x2 "<spaces>name" -- ; Run: -- x1 x2
   1809 \ *G A two-cell equivalent of *\fo{CONSTANT}.
   1810   namedBuild, ,  ;CODE
   1811   sub .s  psp, psp, # 8			\ save TOS
   1812   str     tos, [ psp, # 4 ]
   1813   mov     r0, link			\ LINK is high register
   1814   sub .s  r0, r0, # 1			\ remove T bit
   1815   ldr     tos, [ r0, # 0 ]		\ get data high
   1816   ldr     r1, [ r0, # 4 ]		\ get data low
   1817   str     r1, [ psp, # 0 ]
   1818   pop     { pc }			\ exit
   1819 END-CODE
   1820 
   1821 : VARIABLE 	\ "<spaces>name" -- ; Exec: -- a-addr
   1822 \ *G Create a new variable called *\fo{name}. When *\fo{name} is
   1823 \ ** executed the address of the data-cell is returned for use
   1824 \ ** with *\fo{@} and *\fo{!} operators.
   1825 \ ** The RAM is not initialised.
   1826   rhere namedBuild,  cell rallot  ;CODE
   1827   sub .s  psp, psp, # 4			\ save TOS
   1828   str     tos, [ psp, # 0 ]
   1829   mov     r0, link			\ LINK is high register
   1830   sub .s  r0, r0, # 1			\ remove T bit
   1831   ldr     tos, [ r0, # 0 ]		\ get address
   1832   pop     { pc }
   1833 END-CODE
   1834 
   1835 ((
   1836 : 2VARIABLE	\ Comp: "<spaces>name" -- ; Run: -- a-addr
   1837  \ *G A two-cell equivalent of *\fo{VARIABLE}.
   1838  \ ** The RAM is not initialised.
   1839   rhere namedBuild,  8 rallot  ;CODE
   1840   sub .s  psp, psp, # 4			\ save TOS
   1841   str     tos, [ psp, # 0 ]
   1842   mov     r0, link			\ LINK is high register
   1843   sub .s  r0, r0, # 1			\ remove T bit
   1844   ldr     tos, [ r0, # 0 ]		\ get address
   1845   pop     { pc }
   1846 END-CODE
   1847 ))
   1848 
   1849 : BUFFER:	\ n "<spaces>name" --
   1850  \ *G Create a named buffer in RAM of *\i{n} bytes.
   1851   rhere constant  rallot
   1852 ;
   1853 
   1854 : USER 		\ u "<spaces>name" -- ; Exec: -- addr ; SFP009
   1855 \ *G Create a new *\fo{USER} variable called *\fo{name}. The *\i{u}
   1856 \ ** parameter specifies the index into the user-area table at which
   1857 \ ** to place the* data. *\fo{USER} variables are located in a
   1858 \ ** separate area of memory for each task or interrupt. Use in
   1859 \ ** the form:
   1860 \ *C   $400 USER TaskData
   1861   namedBuild,  ;code			\ ugly, but works
   1862   sub .s  psp, psp, # 4			\ save TOS
   1863   str     tos, [ psp, # 0 ]
   1864   mov     r0, link			\ LINK is high register
   1865   sub .s  r0, r0, # 1			\ remove T bit
   1866   ldr     tos, [ r0, # 0 ]		\ get offset
   1867   add     tos, tos, up			\ add user pointer to user offset
   1868   pop     { pc }
   1869 end-code
   1870 
   1871 interpreter
   1872 : u#		\ "<name>"-- u
   1873 \ *G An *\fo{INTERPRETER} word that returns the index of the
   1874 \ ** *\fo{USER} variable whose name follows, e.g.
   1875 \ *C   u# S0
   1876   ' >body
   1877 ;
   1878 target
   1879 
   1880 internal
   1881 : CRASH 	\ -- ; used as action of DEFER
   1882 \ *G The default action of a *\fo{DEFER}ed word, which is *\fo{NOOP},
   1883 ;
   1884 external
   1885 
   1886 : DEFER 	\ Comp: "<spaces>name" -- ; Run:  i*x -- j*x
   1887 \ *G Creates a new *\fo{DEFER}ed word. No default action is
   1888 \ ** assigned. User-defined *\fo{DEFER}ed words *\b{must} be
   1889 \ ** initialised by the application before use.
   1890 \ *C   ' <action> IS <deferredword>
   1891 \ *P or (when compiled)
   1892 \ *C   ['] <action> IS <deferredword>
   1893   rhere namedBuild,  cell rallot  ;CODE
   1894   mov     r0, link			\ LINK is high register
   1895   sub .s  r0, r0, # 1			\ remove T bit
   1896   ldr     r0, [ r0, # 0 ]		\ get data address
   1897   ldr     r1, [ r0, # 0 ]		\ get xt
   1898   mov .s  r2, # 1
   1899   orr .s  r1, r1, r2			\ force T bit
   1900   pop     { r3 }			\ get return address
   1901   mov     link, r3
   1902   bx      r1
   1903 END-CODE
   1904 
   1905 ((
   1906 : FIELD		\ size n "<spaces>name" -- size+n ; Exec: addr -- addr+n
   1907  \ *G Create a new field of *\i{n} bytes within a structure so far
   1908  \ ** of *\i{size} bytes.
   1909   over namedBuild,  +  ;CODE
   1910   mov     r0, link			\ LINK is high register
   1911   sub .s  r0, r0, # 1			\ remove T bit
   1912   ldr     r1 [ r0, # 0 ]		\ get offset
   1913   add .s  tos, tos, r1			\ add to base addr
   1914   pop     { pc }
   1915 END-CODE
   1916 ))
   1917 
   1918 internal
   1919 variable OPERATORTYPE	\ -- addr ; used at compile time for prefix operator
   1920 
   1921 : VAL-COMPILE/EXECUTE   \ value xt[c] xt[e] --
   1922   state @ if
   1923     drop  compileAligned, ,
   1924   else
   1925     nip  execute
   1926   endif
   1927 ;
   1928 
   1929 : bad-method	\ -- ; error action
   1930   cr ." Invalid operator for this type"
   1931   #-13 throw
   1932 ;
   1933 
   1934 CODE VAL!	\ n -- ; store value address in-line
   1935 \ *G Store n at the inline address following this word.
   1936 \ ** INTERNAL.
   1937 \ N.B. The call to VAL! must be four-byte aligned
   1938   mov     r1, link
   1939   sub .s  r1, r1, # 1		\ inline address
   1940   ldr     r0, [ r1 ]		\ get data address (in-line)
   1941   add .s  r1, r1, # 5		\ step over, restore T bit
   1942   mov     link, r1
   1943   str     tos, [ r0 ]		\ and write data from tos
   1944   ldmia   psp ! { tos }		\ restore TOS
   1945   next,
   1946 END-CODE
   1947 
   1948 CODE VAL@	\ -- n ; read value data address in-line
   1949 \ *G Read n from the inline address following this word.
   1950 \ ** INTERNAL.
   1951 \ N.B. The call to VAL@ must be four-byte aligned
   1952   sub .s  psp, psp, # 4
   1953   str     tos, [ psp ]
   1954   mov     r1, link
   1955   sub .s  r1, r1, # 1		\ inline address
   1956   ldr     r0, [ r1 ]		\ get data address (in-line)
   1957   add .s  r1, r1, # 5		\ step over, restore T bit
   1958   mov     link, r1
   1959   ldr     tos, [ r0 ]		\ read data into tos
   1960   next,
   1961 END-CODE
   1962 
   1963 \ VAL generates a literal, and so LIT is used instead.
   1964 
   1965 external
   1966 
   1967 : VALUE         \ n -- ; --  n ; n VALUE <name>
   1968 \ *G Creates a variable of initial value n that returns its contents
   1969 \ ** when referenced. To store to a child of VALUE use "n to <child>".
   1970 \ ** Application programs must explicity re-initialise children of
   1971 \ ** *\fo{VALUE}.
   1972   Imm
   1973   >r  rhere namedBuild,  r> rhere !  cell rallot
   1974   does>
   1975     case  operatortype @  operatortype off
   1976       0 of  ['] val@  ['] @     val-compile/execute  endof
   1977       1 of  ['] val!  ['] !     val-compile/execute  endof
   1978 \      2 of  state @ if  c_lit  endif                 endof
   1979         bad-method
   1980     endcase
   1981 ;
   1982 
   1983 : to		\ --
   1984 \ *G store operator for use with *\fo{VALUE}s.
   1985   1 OPERATORTYPE !
   1986 ; immediate
   1987 
   1988 
   1989 \ *******************
   1990 \ *S Multitasker hook
   1991 \ *******************
   1992 
   1993 defer pause	\ -- ; multitasker hook
   1994 \ *G Allows the sytem multitasker to get a look in. If the
   1995 \ ** multitasker has not been compiled, *\fo{PAUSE} is set
   1996 \ ** to *\fo{NOOP}.
   1997   assign noop to-do pause
   1998 
   1999 
   2000 \ ************************
   2001 \ *S Structure compilation
   2002 \ ************************
   2003 \ *P These words define high level branches. They are used by the structure
   2004 \ ** words such as *\fo{IF} and *\fo{AGAIN}.
   2005 
   2006 internal
   2007 
   2008 : >mark         \ -- addr
   2009 \ *G Mark the start of a forward branch. HIGH LEVEL CONSTRUCTS ONLY.
   2010 \ ** INTERNAL.
   2011   here  ( 0 , ) cell allot  ;
   2012 
   2013 : >resolve      \ addr --
   2014 \ *G Resolve absolute target of forward branch. HIGH LEVEL CONSTRUCTS ONLY.
   2015 \ ** INTERNAL.
   2016   here 1 or swap !f  ;			\ absolute dest+bit0
   2017 
   2018 : <mark         \ -- addr
   2019 \ *G Mark the start (destination) of a backward branch.
   2020 \ ** HIGH LEVEL CONSTRUCTS ONLY.
   2021 \ ** INTERNAL.
   2022   here  ;
   2023 
   2024 : <resolve      \ addr --
   2025 \ *G Resolve a backward branch to addr.
   2026 \ ** HIGH LEVEL CONSTRUCTS ONLY.
   2027 \ ** INTERNAL.
   2028   1 or ,  ;	               		\ absolute + bit0 for target
   2029 
   2030 synonym >c_res_branch >resolve	\ addr -- ; fix up forward referenced branch
   2031 \ *G See >RESOLVE.
   2032 \ ** INTERNAL.
   2033 synonym c_mrk_branch< <mark	\ -- addr ; mark destination of backward branch
   2034 \ *G See >MARK.
   2035 \ ** INTERNAL.
   2036 
   2037 
   2038 \ **********************
   2039 \ *S Branch constructors
   2040 \ **********************
   2041 \ *P Used when compiling code on the target.
   2042 
   2043 : c_branch<     \ addr --
   2044 \ *G Lay the code for an unconditional backward branch.
   2045 \ ** INTERNAL.
   2046   ['] branch compileAligned, <resolve  ;
   2047 
   2048 : c_?branch<    \ addr --
   2049 \ *G Lay the code for a conditional backward branch.
   2050   ['] ?branch compileAligned, <resolve  ;
   2051 
   2052 : c_branch>     \ -- addr
   2053 \ *G Lay the code for a forward referenced unconditional branch.
   2054 \ ** INTERNAL.
   2055   ['] branch compileAligned,  >mark  ;
   2056 
   2057 : c_?branch>    \ -- addr
   2058 \ *G Lay the code for a forward referenced conditional branch.
   2059 \ ** INTERNAL.
   2060   ['] ?branch compileAligned,  >mark  ;
   2061 
   2062 
   2063 \ *****************
   2064 \ *S Main compilers
   2065 \ *****************
   2066 
   2067 : c_lit		\ lit --
   2068 \ *G Compile the code for a literal of value *\i{lit}.
   2069 \ ** INTERNAL.
   2070   ['] lit compileAligned,  ,  ;
   2071 
   2072 : c_drop        \ --
   2073 \ *G Compile the code for *\fo{DROP}.
   2074 \ ** INTERNAL.
   2075   postpone drop  ;
   2076 
   2077 : c_exit        \ --
   2078 \ *G Compile the code for *\fo{EXIT}.
   2079 \ ** INTERNAL.
   2080   $BD00 w,  ;				\ pop { pc }
   2081 
   2082 : c_do          \ C: -- do-sys ; Run: n1|u1 n2|u2 -- ; R: -- loop-sys
   2083 \ *G Compile the code for *\fo{DO}.
   2084 \ ** INTERNAL.
   2085   ['] (do) compileAligned, >mark <mark  ;
   2086 
   2087 : c_?DO         \ C: -- do-sys ; Run: n1|u1 n2|u2 -- ; R: -- | loop-sys
   2088 \ *G Compile the code for *\fo{?DO}.
   2089 \ ** INTERNAL.
   2090   ['] (?do) compileAligned, >mark <mark  ;
   2091 
   2092 : c_LOOP        \ C: do-sys -- ; Run: -- ; R: loop-sys1 -- | loop-sys2
   2093 \ *G Compile the code for *\fo{LOOP}.
   2094 \ ** INTERNAL.
   2095   ['] (loop) compileAligned, <resolve >resolve  ;
   2096 
   2097 : c_+LOOP       \ C: do-sys -- ; Run: -- ; R: loop-sys1 -- | loop-sys2
   2098 \ *G Compile the code for *\fo{+LOOP}.
   2099 \ ** INTERNAL.
   2100   ['] (+loop) compileAligned, <resolve >resolve  ;
   2101 
   2102 variable NextCaseTarg	\ -- addr
   2103 \ *G Holds the entry point of the current *\fo{CASE} structure.
   2104 \ ** INTERNAL.
   2105 
   2106 : c_case        \ -- addr
   2107 \ *G Compile the code for *\fo{CASE}.
   2108 \ ** INTERNAL.
   2109   NextCaseTarg @  <mark NextCaseTarg !  ;
   2110 
   2111 : c_OF          \ C: -- of-sys ; Run: x1 x2 -- | x1
   2112 \ *G Compile the code for *\fo{OF}.
   2113 \ ** INTERNAL.
   2114   ['] (of) compileAligned, >mark  ;
   2115 
   2116 : c_ENDOF	\ C: case-sys1 of-sys -- case-sys2 ; Run: --
   2117 \ *G Compile the code for *\fo{ENDOF}.
   2118 \ ** INTERNAL.
   2119   c_branch> swap >c_res_branch  ;
   2120 
   2121 : FIX-EXITS     \ n1..nn --
   2122 \ *G Compile the code to resolve the forward branches at the end
   2123 \ ** of a *\fo{CASE} structure.
   2124 \ ** INTERNAL.
   2125   begin
   2126     sp@ csp @ <>
   2127   while
   2128     >c_res_branch
   2129   repeat
   2130 ;
   2131 
   2132 : c_ENDCASE     \ C: case-sys -- ; Run: x --
   2133 \ *G Compile the code for *\fo{ENDCASE}.
   2134 \ ** INTERNAL.
   2135   c_drop  fix-exits  NextCaseTarg !  ;
   2136 
   2137 ((
   2138 : c_END-CASE    \ C: case-sys -- ; Run: x --
   2139   \ *G Compile the code for *\fo{END-CASE}.
   2140   \ ** INTERNAL. Only compiled if the equate *\fo{FullCase?} is non-zero.
   2141   fix-exits  NextCaseTarg !  ;
   2142 ))
   2143 
   2144 : c_NEXTCASE    \ C: case-sys -- ; Run: x --
   2145 \ *G Compile the code for *\fo{NEXTCASE}.
   2146 \ ** INTERNAL.
   2147   c_drop  NextCaseTarg @ c_branch<  fix-exits  NextCaseTarg !  ;
   2148 
   2149 : c_?OF         \ C: -- of-sys ; Run: flag --
   2150 \ *G Compile the code for *\fo{?OF}.
   2151 \ ** INTERNAL.
   2152   c_?branch>  ;
   2153 
   2154 external
   2155 
   2156 
   2157 \ ****************
   2158 \ *S Miscellaneous
   2159 \ ****************
   2160 
   2161 code di		\ --
   2162 \ *G Disable interrupts.
   2163   cps     .id .i
   2164   next,
   2165 end-code
   2166 
   2167 code ei		\ --
   2168 \ *G Enable interrupts.
   2169   cps     .ie .i
   2170   next,
   2171 end-code
   2172 
   2173 code [I		\ R: -- x1 x2
   2174 \ *G Preserve interrupt/exception status on the return stack,
   2175 \ ** and disable interrupts/exceptions except reset, NMI and
   2176 \ ** HardFault. The state is restored by *\fo{I]}.
   2177   mrs     r0, PRIMASK			\ get status
   2178   cps     .id .i
   2179   push .n { r0 }
   2180   next,
   2181 end-code
   2182 
   2183 code I]		\ R: x1 x2 --
   2184 \ *G Restore interrupt status saved by *\fo{[I} from the return
   2185 \ ** stack.
   2186   pop .n  { r0 }
   2187   msr     PRIMASK r0
   2188   next,
   2189 end-code
   2190 
   2191 : setMask	\ value mask addr -- ; cell operation
   2192 \ *G Clear the *\i{mask} bits at *\i{addr} and set (or) the
   2193 \ ** bits defined by *\i{value}.
   2194   tuck @				\ -- value addr mask x
   2195   swap invert and			\ -- value addr x'
   2196   rot or				\ -- addr x''
   2197   swap !
   2198 ;
   2199 
   2200 : init-io	\ addr --
   2201 \ *G Copy the contents of the I/O set up table to an I/O device.
   2202 \ ** Each element of the table is of the form addr (cell) followed
   2203 \ ** by data (cell). The table is terminated by an address of 0.
   2204   begin
   2205     dup @
   2206    while
   2207     dup 2@ !  2 cells +
   2208   repeat
   2209   drop
   2210 ;
   2211 
   2212 
   2213 \ ******
   2214 \ *> ###
   2215 \ ******
   2216 
   2217 decimal