home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / PROG / MISC / EFORTH.ZIP / EFORTH.ASM next >
Encoding:
Assembly Source File  |  1990-07-28  |  45.6 KB  |  2,086 lines

  1. TITLE 8086 eForth
  2.  
  3. PAGE 62,132    ;62 lines per page, 132 characters per line
  4.  
  5. ;===============================================================
  6. ;
  7. ;    eForth 1.0 by Bill Muench and C. H. Ting, 1990
  8. ;    Much of the code is derived from the following sources:
  9. ;        8086 figForth by Thomas Newman, 1981 and Joe smith, 1983
  10. ;        aFORTH by John Rible
  11. ;        bFORTH by Bill Muench
  12. ;
  13. ;    The goal of this implementation is to provide a simple eForth Model
  14. ;    which can be ported easily to many 8, 16, 24 and 32 bit CPU's.
  15. ;    The following attributes make it suitable for CPU's of the '90:
  16. ;
  17. ;        small machine dependent kernel and portable high level code
  18. ;        source code in the MASM format
  19. ;        direct threaded code
  20. ;        separated code and name dictionaries
  21. ;        simple vectored terminal and file interface to host computer
  22. ;        aligned with the proposed ANS Forth Standard
  23. ;        easy upgrade path to optimize for specific CPU
  24. ;
  25. ;    You are invited to implement this Model on your favorite CPU and
  26. ;    contribute it to the eForth Library for public use. You may use
  27. ;    a portable implementation to advertise more sophisticated and
  28. ;    optimized version for commercial purposes. However, you are
  29. ;    expected to implement the Model faithfully. The eForth Working
  30. ;    Group reserves the right to reject implementation which deviates
  31. ;    significantly from this Model.
  32. ;
  33. ;    As the ANS Forth Standard is still evolving, this Model will
  34. ;    change accordingly. Implementations must state clearly the
  35. ;    version number of the Model being tracked.
  36. ;
  37. ;    Representing the eForth Working Group in the Silicon Valley FIG Chapter.
  38. ;    Send contributions to:
  39. ;
  40. ;        Dr. C. H. Ting
  41. ;        156 14th Avenue
  42. ;        San Mateo, CA 94402
  43. ;        (415) 571-7639
  44. ;
  45. ;===============================================================
  46.  
  47. ;; Version control
  48.  
  49. VER        EQU    1            ;major release version
  50. EXT        EQU    0            ;minor extension
  51.  
  52. ;; Constants
  53.  
  54. TRUEE        EQU    -1            ;true flag
  55.  
  56. COMPO        EQU    040H            ;lexicon compile only bit
  57. IMEDD        EQU    080H            ;lexicon immediate bit
  58. MASKK        EQU    07F1FH            ;lexicon bit mask
  59.  
  60. CELLL        EQU    2            ;size of a cell
  61. BASEE        EQU    10            ;default radix
  62. VOCSS        EQU    8            ;depth of vocabulary stack
  63.  
  64. BKSPP        EQU    8            ;back space
  65. LF        EQU    10            ;line feed
  66. CRR        EQU    13            ;carriage return
  67. ERR        EQU    27            ;error escape
  68. TIC        EQU    39            ;tick
  69.  
  70. CALLL        EQU    0E890H            ;NOP CALL opcodes
  71.  
  72. ;; Memory allocation
  73.  
  74. EM        EQU    04000H            ;top of memory
  75. US        EQU    64*CELLL        ;user area size in cells
  76. RTS        EQU    128*CELLL        ;return stack/TIB size
  77.  
  78. UPP        EQU    EM-US            ;start of user area (UP0)
  79. RPP        EQU    UPP-8*CELLL        ;start of return stack (RP0)
  80. TIBB        EQU    RPP-RTS            ;terminal input buffer (TIB)
  81. SPP        EQU    TIBB-8*CELLL        ;start of data stack (SP0)
  82.  
  83. COLDD        EQU    0100H            ;cold start vector
  84. CODEE        EQU    COLDD+US        ;code dictionary
  85. NAMEE        EQU    EM-0400H        ;name dictionary
  86.  
  87. ;; Initialize assembly variables
  88.  
  89. _LINK    = 0                    ;force a null link
  90. _NAME    = NAMEE                    ;initialize name pointer
  91. _CODE    = CODEE                    ;initialize code pointer
  92. _USER    = 4*CELLL                ;first user variable offset
  93.  
  94. ;; Define assembly macros
  95.  
  96. ;    Compile a code definition header.
  97.  
  98. $CODE    MACRO    LEX,NAME,LABEL
  99.     EVEN                    ;;force to cell boundary
  100. LABEL:                        ;;assembly label
  101.     _CODE    = $                ;;save code pointer
  102.     _LEN    = (LEX AND 01FH)/CELLL        ;;string cell count, round down
  103.     _NAME    = _NAME-((_LEN+3)*CELLL)    ;;new header on cell boundary
  104. ORG    _NAME                    ;;set name pointer
  105.     DW     _CODE,_LINK            ;;token pointer and link
  106.     _LINK    = $                ;;link points to a name string
  107.     DB    LEX,NAME            ;;name string
  108. ORG    _CODE                    ;;restore code pointer
  109.     ENDM
  110.  
  111. ;    Compile a colon definition header.
  112.  
  113. $COLON    MACRO    LEX,NAME,LABEL
  114.     $CODE    LEX,NAME,LABEL
  115.     NOP                    ;;align to cell boundary
  116.     CALL    DOLST                ;;include CALL doLIST
  117.     ENDM
  118.  
  119. ;    Compile a user variable header.
  120.  
  121. $USER    MACRO    LEX,NAME,LABEL
  122.     $CODE    LEX,NAME,LABEL
  123.     NOP                    ;;align to cell boundary
  124.     CALL    DOLST                ;;include CALL doLIST
  125.     DW    DOUSE,_USER            ;;followed by doUSER and offset
  126.     _USER = _USER+CELLL            ;;update user area offset
  127.     ENDM
  128.  
  129. ;    Assemble inline direct threaded code ending.
  130.  
  131. $NEXT    MACRO
  132.     LODSW                    ;;read the next code address into AX
  133.     JMP    AX                ;;jump directly to the code address
  134.     ENDM
  135.  
  136. ;; Main entry points and COLD start data
  137.  
  138. MAIN    SEGMENT
  139.     ASSUME    CS:MAIN,DS:MAIN,ES:MAIN,SS:MAIN
  140.  
  141. ORG    COLDD                    ;beginning of cold boot area
  142.  
  143. ORIG:        MOV    AX,CS
  144.         MOV    DS,AX            ;all in one segment
  145.         CLI                ;disable interrupt for old 808x CPU bug
  146.         MOV    SS,AX
  147.         MOV    SP,SPP            ;initialize SP
  148.         STI
  149.         MOV    BP,RPP            ;initialize RP
  150.         MOV    AL,023H            ;^C interrupt Int23
  151.         MOV    DX,OFFSET CTRLC
  152.         MOV    AH,025H            ;set ^C address
  153.         INT    021H
  154.         CLD                ;SI gets incremented
  155.         MOV    SI,OFFSET COLD1
  156.         $NEXT                ;to high level cold start
  157.  
  158. CTRLC:        IRET                ;just return from ^C interrupt Int23
  159.  
  160. ; COLD start moves the following to USER variables.
  161. ; MUST BE IN SAME ORDER AS USER VARIABLES.
  162.  
  163. EVEN                        ;align to cell boundary
  164.  
  165. UZERO:        DW    4 DUP (0)        ;reserved space in user area
  166.         DW    SPP            ;SP0
  167.         DW    RPP            ;RP0
  168.         DW    QRX            ;'?KEY
  169.         DW    TXSTO            ;'EMIT
  170.         DW    ACCEP            ;'EXPECT
  171.         DW    KTAP            ;'TAP
  172.         DW    TXSTO            ;'ECHO
  173.         DW    DOTOK            ;'PROMPT
  174.         DW    BASEE            ;BASE
  175.         DW    0            ;tmp
  176.         DW    0            ;SPAN
  177.         DW    0            ;>IN
  178.         DW    0            ;#TIB
  179.         DW    TIBB            ;TIB
  180.         DW    0            ;CSP
  181.         DW    INTER            ;'EVAL
  182.         DW    NUMBQ            ;'NUMBER
  183.         DW    0            ;HLD
  184.         DW    0            ;HANDLER
  185.         DW    0            ;CONTEXT pointer
  186.         DW    VOCSS DUP (0)        ;vocabulary stack
  187.         DW    0            ;CURRENT pointer
  188.         DW    0            ;vocabulary link pointer
  189.         DW    CTOP            ;CP
  190.         DW    NTOP            ;NP
  191.         DW    LASTN            ;LAST
  192. ULAST:
  193.  
  194. ORG    CODEE                    ;beginning of the code dictionary
  195.  
  196. ;; Device dependent I/O
  197.  
  198. ;   BYE        ( -- )
  199. ;        Exit eForth.
  200.  
  201.         $CODE    3,'BYE',BYE
  202.         INT    020H            ;MS-DOS terminate process
  203.  
  204. ;   ?RX        ( -- c T | F )
  205. ;        Return input character and true, or a false if no input.
  206.  
  207.         $CODE    3,'?RX',QRX
  208.         XOR    BX,BX            ;BX=0 setup for false flag
  209.         MOV    DL,0FFH            ;input command
  210.         MOV    AH,6            ;MS-DOS Direct Console I/O
  211.         INT    021H
  212.         JZ    QRX3            ;?key ready
  213.         OR    AL,AL            ;AL=0 if extended char
  214.         JNZ    QRX1            ;?extended character code
  215.         INT    021H
  216.         MOV    BH,AL            ;extended code in msb
  217.         JMP    QRX2
  218. QRX1:        MOV    BL,AL
  219. QRX2:        PUSH    BX            ;save character
  220.         MOV    BX,TRUEE        ;true flag
  221. QRX3:        PUSH    BX
  222.         $NEXT
  223.  
  224. ;   TX!        ( c -- )
  225. ;        Send character c to the output device.
  226.  
  227.         $CODE    3,'TX!',TXSTO
  228.         POP    DX            ;char in DL
  229.         CMP    DL,0FFH            ;0FFH is interpreted as input
  230.         JNZ    TX1            ;do NOT allow input
  231.         MOV    DL,32            ;change to blank
  232. TX1:        MOV    AH,6            ;MS-DOS Direct Console I/O
  233.         INT    021H            ;display character
  234.         $NEXT
  235.  
  236. ;   !IO        ( -- )
  237. ;        Initialize the serial I/O devices.
  238.  
  239.         $CODE    3,'!IO',STOIO
  240.         $NEXT
  241.  
  242. ;; The kernel
  243.  
  244. ;   doLIT    ( -- w )
  245. ;        Push an inline literal.
  246.  
  247.         $CODE    COMPO+5,'doLIT',DOLIT
  248.         LODSW
  249.         PUSH    AX
  250.         $NEXT
  251.  
  252. ;   doLIST    ( a -- )
  253. ;        Process colon list.
  254.  
  255.         $CODE    COMPO+6,'doLIST',DOLST
  256.         XCHG    BP,SP            ;exchange the return and data stack pointers
  257.         PUSH    SI            ;push on return stack
  258.         XCHG    BP,SP            ;restore the pointers
  259.         POP    SI            ;new list address
  260.         $NEXT
  261.  
  262. ;   next    ( -- )
  263. ;        Run time code for the single index loop.
  264. ;        : next ( -- ) \ hilevel model
  265. ;          r> r> dup if 1 - >r @ >r exit then drop cell+ >r ;
  266.  
  267.         $CODE    COMPO+4,'next',DONXT
  268.         SUB    WORD PTR [BP],1        ;decrement the index
  269.         JC    NEXT1            ;?decrement below 0
  270.         MOV    SI,0[SI]        ;no, branch back again
  271.         $NEXT
  272. NEXT1:        INC    BP            ;yes, pop the index
  273.         INC    BP
  274.         INC    SI            ;continue past the branch offset
  275.         INC    SI
  276.         $NEXT
  277.  
  278. ;   ?branch    ( f -- )
  279. ;        Branch if flag is zero.
  280.  
  281.         $CODE    COMPO+7,'?branch',QBRAN
  282.         POP    BX            ;pop flag
  283.         OR    BX,BX            ;?flag=0
  284.         JZ    BRAN1            ;yes, so branch
  285.         INC    SI            ;point IP to next cell
  286.         INC    SI
  287.         $NEXT
  288. BRAN1:        MOV    SI,0[SI]        ;IP:=(IP)
  289.         $NEXT
  290.  
  291. ;   branch    ( -- )
  292. ;        Branch to an inline address.
  293.  
  294.         $CODE    COMPO+6,'branch',BRAN
  295.         MOV    SI,0[SI]        ;IP:=(IP)
  296.         $NEXT
  297.  
  298. ;   EXECUTE    ( ca -- )
  299. ;        Execute the word at ca.
  300.  
  301.         $CODE    7,'EXECUTE',EXECU
  302.         POP    BX
  303.         JMP    BX            ;jump to the code address
  304.  
  305. ;   EXIT    ( -- )
  306. ;        Terminate a colon definition.
  307.  
  308.         $CODE    4,'EXIT',EXIT
  309.         MOV    SI,[BP]            ;pop return address
  310.         INC    BP            ;adjust RP
  311.         INC    BP
  312.         $NEXT
  313.  
  314. ;   !        ( w a -- )
  315. ;        Pop the data stack to memory.
  316.  
  317.         $CODE    1,'!',STORE
  318.         POP    BX
  319.         POP    0[BX]
  320.         $NEXT
  321.  
  322. ;   @        ( a -- w )
  323. ;        Push memory location to the data stack.
  324.  
  325.         $CODE    1,'@',AT
  326.         POP    BX
  327.         PUSH    0[BX]
  328.         $NEXT
  329.  
  330. ;   C!        ( c b -- )
  331. ;        Pop the data stack to byte memory.
  332.  
  333.         $CODE    2,'C!',CSTOR
  334.         POP    BX
  335.         POP    AX
  336.         MOV    0[BX],AL
  337.         $NEXT
  338.  
  339. ;   C@        ( b -- c )
  340. ;        Push byte memory location to the data stack.
  341.  
  342.         $CODE    2,'C@',CAT
  343.         POP    BX
  344.         XOR    AX,AX            ;AX=0 zero the hi byte
  345.         MOV    AL,0[BX]
  346.         PUSH    AX
  347.         $NEXT
  348.  
  349. ;   RP@        ( -- a )
  350. ;        Push the current RP to the data stack.
  351.  
  352.         $CODE    3,'RP@',RPAT
  353.         PUSH    BP
  354.         $NEXT
  355.  
  356. ;   RP!        ( a -- )
  357. ;        Set the return stack pointer.
  358.  
  359.         $CODE    COMPO+3,'RP!',RPSTO
  360.         POP    BP
  361.         $NEXT
  362.  
  363. ;   R>        ( -- w )
  364. ;        Pop the return stack to the data stack.
  365.  
  366.         $CODE    COMPO+2,'R>',RFROM
  367.         PUSH    0[BP]
  368.         INC    BP            ;adjust RP
  369.         INC    BP
  370.         $NEXT
  371.  
  372. ;   R@        ( -- w )
  373. ;        Copy top of return stack to the data stack.
  374.  
  375.         $CODE    2,'R@',RAT
  376.         PUSH    0[BP]
  377.         $NEXT
  378.  
  379. ;   >R        ( w -- )
  380. ;        Push the data stack to the return stack.
  381.  
  382.         $CODE    COMPO+2,'>R',TOR
  383.         DEC    BP            ;adjust RP
  384.         DEC    BP
  385.         POP    0[BP]            ;push
  386.         $NEXT
  387.  
  388. ;   SP@        ( -- a )
  389. ;        Push the current data stack pointer.
  390.  
  391.         $CODE    3,'SP@',SPAT
  392.         MOV    BX,SP            ;use BX to index the data stack
  393.         PUSH    BX
  394.         $NEXT
  395.  
  396. ;   SP!        ( a -- )
  397. ;        Set the data stack pointer.
  398.  
  399.         $CODE    3,'SP!',SPSTO
  400.         POP    SP
  401.         $NEXT
  402.  
  403. ;   DROP    ( w -- )
  404. ;        Discard top stack item.
  405.  
  406.         $CODE    4,'DROP',DROP
  407.         INC    SP            ;adjust SP
  408.         INC    SP
  409.         $NEXT
  410.  
  411. ;   DUP        ( w -- w w )
  412. ;        Duplicate the top stack item.
  413.  
  414.         $CODE    3,'DUP',DUPP
  415.         MOV    BX,SP            ;use BX to index the data stack
  416.         PUSH    0[BX]
  417.         $NEXT
  418.  
  419. ;   SWAP    ( w1 w2 -- w2 w1 )
  420. ;        Exchange top two stack items.
  421.  
  422.         $CODE    4,'SWAP',SWAP
  423.         POP    BX
  424.         POP    AX
  425.         PUSH    BX
  426.         PUSH    AX
  427.         $NEXT
  428.  
  429. ;   OVER    ( w1 w2 -- w1 w2 w1 )
  430. ;        Copy second stack item to top.
  431.  
  432.         $CODE    4,'OVER',OVER
  433.         MOV    BX,SP            ;use BX to index the stack
  434.         PUSH    2[BX]
  435.         $NEXT
  436.  
  437. ;   0<        ( n -- t )
  438. ;        Return true if n is negative.
  439.  
  440.         $CODE    2,'0<',ZLESS
  441.         POP    AX
  442.         CWD                ;sign extend
  443.         PUSH    DX
  444.         $NEXT
  445.  
  446. ;   AND        ( w w -- w )
  447. ;        Bitwise AND.
  448.  
  449.         $CODE    3,'AND',ANDD
  450.         POP    BX
  451.         POP    AX
  452.         AND    BX,AX
  453.         PUSH    BX
  454.         $NEXT
  455.  
  456. ;   OR        ( w w -- w )
  457. ;        Bitwise inclusive OR.
  458.  
  459.         $CODE    2,'OR',ORR
  460.         POP    BX
  461.         POP    AX
  462.         OR    BX,AX
  463.         PUSH    BX
  464.         $NEXT
  465.  
  466. ;   XOR        ( w w -- w )
  467. ;        Bitwise exclusive OR.
  468.  
  469.         $CODE    3,'XOR',XORR
  470.         POP    BX
  471.         POP    AX
  472.         XOR    BX,AX
  473.         PUSH    BX
  474.         $NEXT
  475.  
  476. ;   UM+        ( u u -- udsum )
  477. ;        Add two unsigned single numbers and return a double sum.
  478.  
  479.         $CODE    3,'UM+',UPLUS
  480.         XOR    CX,CX            ;CX=0 initial carry flag
  481.         POP    BX
  482.         POP    AX
  483.         ADD    AX,BX
  484.         RCL    CX,1            ;get carry
  485.         PUSH    AX            ;push sum
  486.         PUSH    CX            ;push carry
  487.         $NEXT
  488.  
  489. ;; System and user variables
  490.  
  491. ;   doVAR    ( -- a )
  492. ;        Run time routine for VARIABLE and CREATE.
  493.  
  494.         $COLON    COMPO+5,'doVAR',DOVAR
  495.         DW    RFROM,EXIT
  496.  
  497. ;   UP        ( -- a )
  498. ;        Pointer to the user area.
  499.  
  500.         $COLON    2,'UP',UP
  501.         DW    DOVAR
  502.         DW    UPP
  503.  
  504. ;   doUSER    ( -- a )
  505. ;        Run time routine for user variables.
  506.  
  507.         $COLON    COMPO+6,'doUSER',DOUSE
  508.         DW    RFROM,AT,UP,AT,PLUS,EXIT
  509.  
  510. ;   SP0        ( -- a )
  511. ;        Pointer to bottom of the data stack.
  512.  
  513.         $USER    3,'SP0',SZERO
  514.  
  515. ;   RP0        ( -- a )
  516. ;        Pointer to bottom of the return stack.
  517.  
  518.         $USER    3,'RP0',RZERO
  519.  
  520. ;   '?KEY    ( -- a )
  521. ;        Execution vector of ?KEY.
  522.  
  523.         $USER    5,"'?KEY",TQKEY
  524.  
  525. ;   'EMIT    ( -- a )
  526. ;        Execution vector of EMIT.
  527.  
  528.         $USER    5,"'EMIT",TEMIT
  529.  
  530. ;   'EXPECT    ( -- a )
  531. ;        Execution vector of EXPECT.
  532.  
  533.         $USER    7,"'EXPECT",TEXPE
  534.  
  535. ;   'TAP    ( -- a )
  536. ;        Execution vector of TAP.
  537.  
  538.         $USER    4,"'TAP",TTAP
  539.  
  540. ;   'ECHO    ( -- a )
  541. ;        Execution vector of ECHO.
  542.  
  543.         $USER    5,"'ECHO",TECHO
  544.  
  545. ;   'PROMPT    ( -- a )
  546. ;        Execution vector of PROMPT.
  547.  
  548.         $USER    7,"'PROMPT",TPROM
  549.  
  550. ;   BASE    ( -- a )
  551. ;        Storage of the radix base for numeric I/O.
  552.  
  553.         $USER    4,'BASE',BASE
  554.  
  555. ;   tmp        ( -- a )
  556. ;        A temporary storage location used in parse and find.
  557.  
  558.         $USER    COMPO+3,'tmp',TEMP
  559.  
  560. ;   SPAN    ( -- a )
  561. ;        Hold character count received by EXPECT.
  562.  
  563.         $USER    4,'SPAN',SPAN
  564.  
  565. ;   >IN        ( -- a )
  566. ;        Hold the character pointer while parsing input stream.
  567.  
  568.         $USER    3,'>IN',INN
  569.  
  570. ;   #TIB    ( -- a )
  571. ;        Hold the current count in and address of the terminal input buffer.
  572.  
  573.         $USER    4,'#TIB',NTIB
  574.         _USER = _USER+CELLL        ;hold the base address of the terminal input buffer
  575.  
  576. ;   CSP        ( -- a )
  577. ;        Hold the stack pointer for error checking.
  578.  
  579.         $USER    3,'CSP',CSP
  580.  
  581. ;   'EVAL    ( -- a )
  582. ;        Execution vector of EVAL.
  583.  
  584.         $USER    5,"'EVAL",TEVAL
  585.  
  586. ;   'NUMBER    ( -- a )
  587. ;        Execution vector of NUMBER?.
  588.  
  589.         $USER    7,"'NUMBER",TNUMB
  590.  
  591. ;   HLD        ( -- a )
  592. ;        Hold a pointer in building a numeric output string.
  593.  
  594.         $USER    3,'HLD',HLD
  595.  
  596. ;   HANDLER    ( -- a )
  597. ;        Hold the return stack pointer for error handling.
  598.  
  599.         $USER    7,'HANDLER',HANDL
  600.  
  601. ;   CONTEXT    ( -- a )
  602. ;        A area to specify vocabulary search order.
  603.  
  604.         $USER    7,'CONTEXT',CNTXT
  605.         _USER = _USER+VOCSS*CELLL    ;vocabulary stack
  606.  
  607. ;   CURRENT    ( -- a )
  608. ;        Point to the vocabulary to be extended.
  609.  
  610.         $USER    7,'CURRENT',CRRNT
  611.         _USER = _USER+CELLL        ;vocabulary link pointer
  612.  
  613. ;   CP        ( -- a )
  614. ;        Point to the top of the code dictionary.
  615.  
  616.         $USER    2,'CP',CP
  617.  
  618. ;   NP        ( -- a )
  619. ;        Point to the bottom of the name dictionary.
  620.  
  621.         $USER    2,'NP',NP
  622.  
  623. ;   LAST    ( -- a )
  624. ;        Point to the last name in the name dictionary.
  625.  
  626.         $USER    4,'LAST',LAST
  627.  
  628. ;; Common functions
  629.  
  630. ;   doVOC    ( -- )
  631. ;        Run time action of VOCABULARY's.
  632.  
  633.         $COLON    COMPO+5,'doVOC',DOVOC
  634.         DW    RFROM,CNTXT,STORE,EXIT
  635.  
  636. ;   FORTH    ( -- )
  637. ;        Make FORTH the context vocabulary.
  638.  
  639.         $COLON    5,'FORTH',FORTH
  640.         DW    DOVOC
  641.         DW    0            ;vocabulary head pointer
  642.         DW    0            ;vocabulary link pointer
  643.  
  644. ;   ?DUP    ( w -- w w | 0 )
  645. ;        Dup tos if its is not zero.
  646.  
  647.         $COLON    4,'?DUP',QDUP
  648.         DW    DUPP
  649.         DW    QBRAN,QDUP1
  650.         DW    DUPP
  651. QDUP1:        DW    EXIT
  652.  
  653. ;   ROT        ( w1 w2 w3 -- w2 w3 w1 )
  654. ;        Rot 3rd item to top.
  655.  
  656.         $COLON    3,'ROT',ROT
  657.         DW    TOR,SWAP,RFROM,SWAP,EXIT
  658.  
  659. ;   2DROP    ( w w -- )
  660. ;        Discard two items on stack.
  661.  
  662.         $COLON    5,'2DROP',DDROP
  663.         DW    DROP,DROP,EXIT
  664.  
  665. ;   2DUP    ( w1 w2 -- w1 w2 w1 w2 )
  666. ;        Duplicate top two items.
  667.  
  668.         $COLON    4,'2DUP',DDUP
  669.         DW    OVER,OVER,EXIT
  670.  
  671. ;   +        ( w w -- sum )
  672. ;        Add top two items.
  673.  
  674.         $COLON    1,'+',PLUS
  675.         DW    UPLUS,DROP,EXIT
  676.  
  677. ;   NOT        ( w -- w )
  678. ;        One's complement of tos.
  679.  
  680.         $COLON    3,'NOT',INVER
  681.         DW    DOLIT,-1,XORR,EXIT
  682.  
  683. ;   NEGATE    ( n -- -n )
  684. ;        Two's complement of tos.
  685.  
  686.         $COLON    6,'NEGATE',NEGAT
  687.         DW    INVER,DOLIT,1,PLUS,EXIT
  688.  
  689. ;   DNEGATE    ( d -- -d )
  690. ;        Two's complement of top double.
  691.  
  692.         $COLON    7,'DNEGATE',DNEGA
  693.         DW    INVER,TOR,INVER
  694.         DW    DOLIT,1,UPLUS
  695.         DW    RFROM,PLUS,EXIT
  696.  
  697. ;   -        ( n1 n2 -- n1-n2 )
  698. ;        Subtraction.
  699.  
  700.         $COLON    1,'-',SUBB
  701.         DW    NEGAT,PLUS,EXIT
  702.  
  703. ;   ABS        ( n -- n )
  704. ;        Return the absolute value of n.
  705.  
  706.         $COLON    3,'ABS',ABSS
  707.         DW    DUPP,ZLESS
  708.         DW    QBRAN,ABS1
  709.         DW    NEGAT
  710. ABS1:        DW    EXIT
  711.  
  712. ;   =        ( w w -- t )
  713. ;        Return true if top two are equal.
  714.  
  715.         $COLON    1,'=',EQUAL
  716.         DW    XORR
  717.         DW    QBRAN,EQU1
  718.         DW    DOLIT,0,EXIT
  719. EQU1:        DW    DOLIT,TRUEE,EXIT
  720.  
  721. ;   U<        ( u u -- t )
  722. ;        Unsigned compare of top two items.
  723.  
  724.         $COLON    2,'U<',ULESS
  725.         DW    DDUP,XORR,ZLESS
  726.         DW    QBRAN,ULES1
  727.         DW    SWAP,DROP,ZLESS,EXIT
  728. ULES1:        DW    SUBB,ZLESS,EXIT
  729.  
  730. ;   <        ( n1 n2 -- t )
  731. ;        Signed compare of top two items.
  732.  
  733.         $COLON    1,'<',LESS
  734.         DW    DDUP,XORR,ZLESS
  735.         DW    QBRAN,LESS1
  736.         DW    DROP,ZLESS,EXIT
  737. LESS1:        DW    SUBB,ZLESS,EXIT
  738.  
  739. ;   MAX        ( n n -- n )
  740. ;        Return the greater of two top stack items.
  741.  
  742.         $COLON    3,'MAX',MAX
  743.         DW    DDUP,LESS
  744.         DW    QBRAN,MAX1
  745.         DW    SWAP
  746. MAX1:        DW    DROP,EXIT
  747.  
  748. ;   MIN        ( n n -- n )
  749. ;        Return the smaller of top two stack items.
  750.  
  751.         $COLON    3,'MIN',MIN
  752.         DW    DDUP,SWAP,LESS
  753.         DW    QBRAN,MIN1
  754.         DW    SWAP
  755. MIN1:        DW    DROP,EXIT
  756.  
  757. ;   WITHIN    ( u ul uh -- t )
  758. ;        Return true if u is within the range of ul and uh. ( ul <= u < uh )
  759.  
  760.         $COLON    6,'WITHIN',WITHI
  761.         DW    OVER,SUBB,TOR
  762.         DW    SUBB,RFROM,ULESS,EXIT
  763.  
  764. ;; Divide
  765.  
  766. ;   UM/MOD    ( udl udh un -- ur uq )
  767. ;        Unsigned divide of a double by a single. Return mod and quotient.
  768.  
  769.         $COLON    6,'UM/MOD',UMMOD
  770.         DW    DDUP,ULESS
  771.         DW    QBRAN,UMM4
  772.         DW    NEGAT,DOLIT,15,TOR
  773. UMM1:        DW    TOR,DUPP,UPLUS
  774.         DW    TOR,TOR,DUPP,UPLUS
  775.         DW    RFROM,PLUS,DUPP
  776.         DW    RFROM,RAT,SWAP,TOR
  777.         DW    UPLUS,RFROM,ORR
  778.         DW    QBRAN,UMM2
  779.         DW    TOR,DROP,DOLIT,1,PLUS,RFROM
  780.         DW    BRAN,UMM3
  781. UMM2:        DW    DROP
  782. UMM3:        DW    RFROM
  783.         DW    DONXT,UMM1
  784.         DW    DROP,SWAP,EXIT
  785. UMM4:        DW    DROP,DDROP
  786.         DW    DOLIT,-1,DUPP,EXIT
  787.  
  788. ;   M/MOD    ( d n -- r q )
  789. ;        Signed floored divide of double by single. Return mod and quotient.
  790.  
  791.         $COLON    5,'M/MOD',MSMOD
  792.         DW    DUPP,ZLESS,DUPP,TOR
  793.         DW    QBRAN,MMOD1
  794.         DW    NEGAT,TOR,DNEGA,RFROM
  795. MMOD1:        DW    TOR,DUPP,ZLESS
  796.         DW    QBRAN,MMOD2
  797.         DW    RAT,PLUS
  798. MMOD2:        DW    RFROM,UMMOD,RFROM
  799.         DW    QBRAN,MMOD3
  800.         DW    SWAP,NEGAT,SWAP
  801. MMOD3:        DW    EXIT
  802.  
  803. ;   /MOD    ( n n -- r q )
  804. ;        Signed divide. Return mod and quotient.
  805.  
  806.         $COLON    4,'/MOD',SLMOD
  807.         DW    OVER,ZLESS,SWAP,MSMOD,EXIT
  808.  
  809. ;   MOD        ( n n -- r )
  810. ;        Signed divide. Return mod only.
  811.  
  812.         $COLON    3,'MOD',MODD
  813.         DW    SLMOD,DROP,EXIT
  814.  
  815. ;   /        ( n n -- q )
  816. ;        Signed divide. Return quotient only.
  817.  
  818.         $COLON    1,'/',SLASH
  819.         DW    SLMOD,SWAP,DROP,EXIT
  820.  
  821. ;; Multiply
  822.  
  823. ;   UM*        ( u u -- ud )
  824. ;        Unsigned multiply. Return double product.
  825.  
  826.         $COLON    3,'UM*',UMSTA
  827.         DW    DOLIT,0,SWAP,DOLIT,15,TOR
  828. UMST1:        DW    DUPP,UPLUS,TOR,TOR
  829.         DW    DUPP,UPLUS,RFROM,PLUS,RFROM
  830.         DW    QBRAN,UMST2
  831.         DW    TOR,OVER,UPLUS,RFROM,PLUS
  832. UMST2:        DW    DONXT,UMST1
  833.         DW    ROT,DROP,EXIT
  834.  
  835. ;   *        ( n n -- n )
  836. ;        Signed multiply. Return single product.
  837.  
  838.         $COLON    1,'*',STAR
  839.         DW    UMSTA,DROP,EXIT
  840.  
  841. ;   M*        ( n n -- d )
  842. ;        Signed multiply. Return double product.
  843.  
  844.         $COLON    2,'M*',MSTAR
  845.         DW    DDUP,XORR,ZLESS,TOR
  846.         DW    ABSS,SWAP,ABSS,UMSTA
  847.         DW    RFROM
  848.         DW    QBRAN,MSTA1
  849.         DW    DNEGA
  850. MSTA1:        DW    EXIT
  851.  
  852. ;   */MOD    ( n1 n2 n3 -- r q )
  853. ;        Multiply n1 and n2, then divide by n3. Return mod and quotient.
  854.  
  855.         $COLON    5,'*/MOD',SSMOD
  856.         DW    TOR,MSTAR,RFROM,MSMOD,EXIT
  857.  
  858. ;   */        ( n1 n2 n3 -- q )
  859. ;        Multiply n1 by n2, then divide by n3. Return quotient only.
  860.  
  861.         $COLON    2,'*/',STASL
  862.         DW    SSMOD,SWAP,DROP,EXIT
  863.  
  864. ;; Miscellaneous
  865.  
  866. ;   CELL+    ( a -- a )
  867. ;        Add cell size in byte to address.
  868.  
  869.         $COLON    5,'CELL+',CELLP
  870.         DW    DOLIT,CELLL,PLUS,EXIT
  871.  
  872. ;   CELL-    ( a -- a )
  873. ;        Subtract cell size in byte from address.
  874.  
  875.         $COLON    5,'CELL-',CELLM
  876.         DW    DOLIT,0-CELLL,PLUS,EXIT
  877.  
  878. ;   CELLS    ( n -- n )
  879. ;        Multiply tos by cell size in bytes.
  880.  
  881.         $COLON    5,'CELLS',CELLS
  882.         DW    DOLIT,CELLL,STAR,EXIT
  883.  
  884. ;   ALIGNED    ( b -- a )
  885. ;        Align address to the cell boundary.
  886.  
  887.         $COLON    7,'ALIGNED',ALGND
  888.         DW    DUPP,DOLIT,0,DOLIT,CELLL
  889.         DW    UMMOD,DROP,DUPP
  890.         DW    QBRAN,ALGN1
  891.         DW    DOLIT,CELLL,SWAP,SUBB
  892. ALGN1:        DW    PLUS,EXIT
  893.  
  894. ;   BL        ( -- 32 )
  895. ;        Return 32, the blank character.
  896.  
  897.         $COLON    2,'BL',BLANK
  898.         DW    DOLIT,' ',EXIT
  899.  
  900. ;   >CHAR    ( c -- c )
  901. ;        Filter non-printing characters.
  902.  
  903.         $COLON    5,'>CHAR',TCHAR
  904.         DW    DOLIT,07FH,ANDD,DUPP    ;mask msb
  905.         DW    DOLIT,127,BLANK,WITHI    ;check for printable
  906.         DW    QBRAN,TCHA1
  907.         DW    DROP,DOLIT,'_'        ;replace non-printables
  908. TCHA1:        DW    EXIT
  909.  
  910. ;   DEPTH    ( -- n )
  911. ;        Return the depth of the data stack.
  912.  
  913.         $COLON    5,'DEPTH',DEPTH
  914.         DW    SPAT,SZERO,AT,SWAP,SUBB
  915.         DW    DOLIT,CELLL,SLASH,EXIT
  916.  
  917. ;   PICK    ( ... +n -- ... w )
  918. ;        Copy the nth stack item to tos.
  919.  
  920.         $COLON    4,'PICK',PICK
  921.         DW    DOLIT,1,PLUS,CELLS
  922.         DW    SPAT,PLUS,AT,EXIT
  923.  
  924. ;; Memory access
  925.  
  926. ;   +!        ( n a -- )
  927. ;        Add n to the contents at address a.
  928.  
  929.         $COLON    2,'+!',PSTOR
  930.         DW    SWAP,OVER,AT,PLUS
  931.         DW    SWAP,STORE,EXIT
  932.  
  933. ;   2!        ( d a -- )
  934. ;        Store the double integer to address a.
  935.  
  936.         $COLON    2,'2!',DSTOR
  937.         DW    SWAP,OVER,STORE
  938.         DW    CELLP,STORE,EXIT
  939.  
  940. ;   2@        ( a -- d )
  941. ;        Fetch double integer from address a.
  942.  
  943.         $COLON    2,'2@',DAT
  944.         DW    DUPP,CELLP,AT
  945.         DW    SWAP,AT,EXIT
  946.  
  947. ;   COUNT    ( b -- b +n )
  948. ;        Return count byte of a string and add 1 to byte address.
  949.  
  950.         $COLON    5,'COUNT',COUNT
  951.         DW    DUPP,DOLIT,1,PLUS
  952.         DW    SWAP,CAT,EXIT
  953.  
  954. ;   HERE    ( -- a )
  955. ;        Return the top of the code dictionary.
  956.  
  957.         $COLON    4,'HERE',HERE
  958.         DW    CP,AT,EXIT
  959.  
  960. ;   PAD        ( -- a )
  961. ;        Return the address of the text buffer above the code dictionary.
  962.  
  963.         $COLON    3,'PAD',PAD
  964.         DW    HERE,DOLIT,80,PLUS,EXIT
  965.  
  966. ;   TIB        ( -- a )
  967. ;        Return the address of the terminal input buffer.
  968.  
  969.         $COLON    3,'TIB',TIB
  970.         DW    NTIB,CELLP,AT,EXIT
  971.  
  972. ;   @EXECUTE    ( a -- )
  973. ;        Execute vector stored in address a.
  974.  
  975.         $COLON    8,'@EXECUTE',ATEXE
  976.         DW    AT,QDUP            ;?address or zero
  977.         DW    QBRAN,EXE1
  978.         DW    EXECU            ;execute if non-zero
  979. EXE1:        DW    EXIT            ;do nothing if zero
  980.  
  981. ;   CMOVE    ( b1 b2 u -- )
  982. ;        Copy u bytes from b1 to b2.
  983.  
  984.         $COLON    5,'CMOVE',CMOVE
  985.         DW    TOR
  986.         DW    BRAN,CMOV2
  987. CMOV1:        DW    TOR,DUPP,CAT
  988.         DW    RAT,CSTOR
  989.         DW    DOLIT,1,PLUS
  990.         DW    RFROM,DOLIT,1,PLUS
  991. CMOV2:        DW    DONXT,CMOV1
  992.         DW    DDROP,EXIT
  993.  
  994. ;   FILL    ( b u c -- )
  995. ;        Fill u bytes of character c to area beginning at b.
  996.  
  997.         $COLON    4,'FILL',FILL
  998.         DW    SWAP,TOR,SWAP
  999.         DW    BRAN,FILL2
  1000. FILL1:        DW    DDUP,CSTOR,DOLIT,1,PLUS
  1001. FILL2:        DW    DONXT,FILL1
  1002.         DW    DDROP,EXIT
  1003.  
  1004. ;   -TRAILING    ( b u -- b u )
  1005. ;        Adjust the count to eliminate trailing white space.
  1006.  
  1007.         $COLON    9,'-TRAILING',DTRAI
  1008.         DW    TOR
  1009.         DW    BRAN,DTRA2
  1010. DTRA1:        DW    BLANK,OVER,RAT,PLUS,CAT,LESS
  1011.         DW    QBRAN,DTRA2
  1012.         DW    RFROM,DOLIT,1,PLUS,EXIT
  1013. DTRA2:        DW    DONXT,DTRA1
  1014.         DW    DOLIT,0,EXIT
  1015.  
  1016. ;   PACK$    ( b u a -- a )
  1017. ;        Build a counted string with u characters from b. Null fill.
  1018.  
  1019.         $COLON    5,'PACK$',PACKS
  1020.         DW    ALGND,DUPP,TOR        ;strings only on cell boundary
  1021.         DW    OVER,DUPP,DOLIT,0
  1022.         DW    DOLIT,CELLL,UMMOD,DROP    ;count mod cell
  1023.         DW    SUBB,OVER,PLUS
  1024.         DW    DOLIT,0,SWAP,STORE    ;null fill cell
  1025.         DW    DDUP,CSTOR,DOLIT,1,PLUS    ;save count
  1026.         DW    SWAP,CMOVE,RFROM,EXIT    ;move string
  1027.  
  1028. ;; Numeric output, single precision
  1029.  
  1030. ;   DIGIT    ( u -- c )
  1031. ;        Convert digit u to a character.
  1032.  
  1033.         $COLON    5,'DIGIT',DIGIT
  1034.         DW    DOLIT,9,OVER,LESS
  1035.         DW    DOLIT,7,ANDD,PLUS
  1036.         DW    DOLIT,'0',PLUS,EXIT
  1037.  
  1038. ;   EXTRACT    ( n base -- n c )
  1039. ;        Extract the least significant digit from n.
  1040.  
  1041.         $COLON    7,'EXTRACT',EXTRC
  1042.         DW    DOLIT,0,SWAP,UMMOD
  1043.         DW    SWAP,DIGIT,EXIT
  1044.  
  1045. ;   <#        ( -- )
  1046. ;        Initiate the numeric output process.
  1047.  
  1048.         $COLON    2,'<#',BDIGS
  1049.         DW    PAD,HLD,STORE,EXIT
  1050.  
  1051. ;   HOLD    ( c -- )
  1052. ;        Insert a character into the numeric output string.
  1053.  
  1054.         $COLON    4,'HOLD',HOLD
  1055.         DW    HLD,AT,DOLIT,1,SUBB
  1056.         DW    DUPP,HLD,STORE,CSTOR,EXIT
  1057.  
  1058. ;   #        ( u -- u )
  1059. ;        Extract one digit from u and append the digit to output string.
  1060.  
  1061.         $COLON    1,'#',DIG
  1062.         DW    BASE,AT,EXTRC,HOLD,EXIT
  1063.  
  1064. ;   #S        ( u -- 0 )
  1065. ;        Convert u until all digits are added to the output string.
  1066.  
  1067.         $COLON    2,'#S',DIGS
  1068. DIGS1:        DW    DIG,DUPP
  1069.         DW    QBRAN,DIGS2
  1070.         DW    BRAN,DIGS1
  1071. DIGS2:        DW    EXIT
  1072.  
  1073. ;   SIGN    ( n -- )
  1074. ;        Add a minus sign to the numeric output string.
  1075.  
  1076.         $COLON    4,'SIGN',SIGN
  1077.         DW    ZLESS
  1078.         DW    QBRAN,SIGN1
  1079.         DW    DOLIT,'-',HOLD
  1080. SIGN1:        DW    EXIT
  1081.  
  1082. ;   #>        ( w -- b u )
  1083. ;        Prepare the output string to be TYPE'd.
  1084.  
  1085.         $COLON    2,'#>',EDIGS
  1086.         DW    DROP,HLD,AT
  1087.         DW    PAD,OVER,SUBB,EXIT
  1088.  
  1089. ;   str        ( w -- b u )
  1090. ;        Convert a signed integer to a numeric string.
  1091.  
  1092.         $COLON    3,'str',STR
  1093.         DW    DUPP,TOR,ABSS
  1094.         DW    BDIGS,DIGS,RFROM
  1095.         DW    SIGN,EDIGS,EXIT
  1096.  
  1097. ;   HEX        ( -- )
  1098. ;        Use radix 16 as base for numeric conversions.
  1099.  
  1100.         $COLON    3,'HEX',HEX
  1101.         DW    DOLIT,16,BASE,STORE,EXIT
  1102.  
  1103. ;   DECIMAL    ( -- )
  1104. ;        Use radix 10 as base for numeric conversions.
  1105.  
  1106.         $COLON    7,'DECIMAL',DECIM
  1107.         DW    DOLIT,10,BASE,STORE,EXIT
  1108.  
  1109. ;; Numeric input, single precision
  1110.  
  1111. ;   DIGIT?    ( c base -- u t )
  1112. ;        Convert a character to its numeric value. A flag indicates success.
  1113.  
  1114.         $COLON    6,'DIGIT?',DIGTQ
  1115.         DW    TOR,DOLIT,'0',SUBB
  1116.         DW    DOLIT,9,OVER,LESS
  1117.         DW    QBRAN,DGTQ1
  1118.         DW    DOLIT,7,SUBB
  1119.         DW    DUPP,DOLIT,10,LESS,ORR
  1120. DGTQ1:        DW    DUPP,RFROM,ULESS,EXIT
  1121.  
  1122. ;   NUMBER?    ( a -- n T | a F )
  1123. ;        Convert a number string to integer. Push a flag on tos.
  1124.  
  1125.         $COLON    7,'NUMBER?',NUMBQ
  1126.         DW    BASE,AT,TOR,DOLIT,0,OVER,COUNT
  1127.         DW    OVER,CAT,DOLIT,'$',EQUAL
  1128.         DW    QBRAN,NUMQ1
  1129.         DW    HEX,SWAP,DOLIT,1,PLUS
  1130.         DW    SWAP,DOLIT,1,SUBB
  1131. NUMQ1:        DW    OVER,CAT,DOLIT,'-',EQUAL,TOR
  1132.         DW    SWAP,RAT,SUBB,SWAP,RAT,PLUS,QDUP
  1133.         DW    QBRAN,NUMQ6
  1134.         DW    DOLIT,1,SUBB,TOR
  1135. NUMQ2:        DW    DUPP,TOR,CAT,BASE,AT,DIGTQ
  1136.         DW    QBRAN,NUMQ4
  1137.         DW    SWAP,BASE,AT,STAR,PLUS,RFROM
  1138.         DW    DOLIT,1,PLUS
  1139.         DW    DONXT,NUMQ2
  1140.         DW    RAT,SWAP,DROP
  1141.         DW    QBRAN,NUMQ3
  1142.         DW    NEGAT
  1143. NUMQ3:        DW    SWAP
  1144.         DW    BRAN,NUMQ5
  1145. NUMQ4:        DW    RFROM,RFROM,DDROP,DDROP,DOLIT,0
  1146. NUMQ5:        DW    DUPP
  1147. NUMQ6:        DW    RFROM,DDROP
  1148.         DW    RFROM,BASE,STORE,EXIT
  1149.  
  1150. ;; Basic I/O
  1151.  
  1152. ;   ?KEY    ( -- c T | F )
  1153. ;        Return input character and true, or a false if no input.
  1154.  
  1155.         $COLON    4,'?KEY',QKEY
  1156.         DW    TQKEY,ATEXE,EXIT
  1157.  
  1158. ;   KEY        ( -- c )
  1159. ;        Wait for and return an input character.
  1160.  
  1161.         $COLON    3,'KEY',KEY
  1162. KEY1:        DW    QKEY
  1163.         DW    QBRAN,KEY1
  1164.         DW    EXIT
  1165.  
  1166. ;   EMIT    ( c -- )
  1167. ;        Send a character to the output device.
  1168.  
  1169.         $COLON    4,'EMIT',EMIT
  1170.         DW    TEMIT,ATEXE,EXIT
  1171.  
  1172. ;   NUF?    ( -- t )
  1173. ;        Return false if no input, else pause and if CR return true.
  1174.  
  1175.         $COLON    4,'NUF?',NUFQ
  1176.         DW    QKEY,DUPP
  1177.         DW    QBRAN,NUFQ1
  1178.         DW    DDROP,KEY,DOLIT,CRR,EQUAL
  1179. NUFQ1:        DW    EXIT
  1180.  
  1181. ;   PACE    ( -- )
  1182. ;        Send a pace character for the file downloading process.
  1183.  
  1184.         $COLON    4,'PACE',PACE
  1185.         DW    DOLIT,11,EMIT,EXIT
  1186.  
  1187. ;   SPACE    ( -- )
  1188. ;        Send the blank character to the output device.
  1189.  
  1190.         $COLON    5,'SPACE',SPACE
  1191.         DW    BLANK,EMIT,EXIT
  1192.  
  1193. ;   SPACES    ( +n -- )
  1194. ;        Send n spaces to the output device.
  1195.  
  1196.         $COLON    6,'SPACES',SPACS
  1197.         DW    DOLIT,0,MAX,TOR
  1198.         DW    BRAN,CHAR2
  1199. CHAR1:        DW    SPACE
  1200. CHAR2:        DW    DONXT,CHAR1
  1201.         DW    EXIT
  1202.  
  1203. ;   TYPE    ( b u -- )
  1204. ;        Output u characters from b.
  1205.  
  1206.         $COLON    4,'TYPE',TYPES
  1207.         DW    TOR
  1208.         DW    BRAN,TYPE2
  1209. TYPE1:        DW    DUPP,CAT,EMIT
  1210.         DW    DOLIT,1,PLUS
  1211. TYPE2:        DW    DONXT,TYPE1
  1212.         DW    DROP,EXIT
  1213.  
  1214. ;   CR        ( -- )
  1215. ;        Output a carriage return and a line feed.
  1216.  
  1217.         $COLON    2,'CR',CR
  1218.         DW    DOLIT,CRR,EMIT
  1219.         DW    DOLIT,LF,EMIT,EXIT
  1220.  
  1221. ;   do$        ( -- a )
  1222. ;        Return the address of a compiled string.
  1223.  
  1224.         $COLON    COMPO+3,'do$',DOSTR
  1225.         DW    RFROM,RAT,RFROM,COUNT,PLUS
  1226.         DW    ALGND,TOR,SWAP,TOR,EXIT
  1227.  
  1228. ;   $"|        ( -- a )
  1229. ;        Run time routine compiled by $". Return address of a compiled string.
  1230.  
  1231.         $COLON    COMPO+3,'$"|',STRQP
  1232.         DW    DOSTR,EXIT        ;force a call to do$
  1233.  
  1234. ;   ."|        ( -- )
  1235. ;        Run time routine of ." . Output a compiled string.
  1236.  
  1237.         $COLON    COMPO+3,'."|',DOTQP
  1238.         DW    DOSTR,COUNT,TYPES,EXIT
  1239.  
  1240. ;   .R        ( n +n -- )
  1241. ;        Display an integer in a field of n columns, right justified.
  1242.  
  1243.         $COLON    2,'.R',DOTR
  1244.         DW    TOR,STR,RFROM,OVER,SUBB
  1245.         DW    SPACS,TYPES,EXIT
  1246.  
  1247. ;   U.R        ( u +n -- )
  1248. ;        Display an unsigned integer in n column, right justified.
  1249.  
  1250.         $COLON    3,'U.R',UDOTR
  1251.         DW    TOR,BDIGS,DIGS,EDIGS
  1252.         DW    RFROM,OVER,SUBB
  1253.         DW    SPACS,TYPES,EXIT
  1254.  
  1255. ;   U.        ( u -- )
  1256. ;        Display an unsigned integer in free format.
  1257.  
  1258.         $COLON    2,'U.',UDOT
  1259.         DW    BDIGS,DIGS,EDIGS
  1260.         DW    SPACE,TYPES,EXIT
  1261.  
  1262. ;   .        ( w -- )
  1263. ;        Display an integer in free format, preceeded by a space.
  1264.  
  1265.         $COLON    1,'.',DOT
  1266.         DW    BASE,AT,DOLIT,10,XORR    ;?decimal
  1267.         DW    QBRAN,DOT1
  1268.         DW    UDOT,EXIT        ;no, display unsigned
  1269. DOT1:        DW    STR,SPACE,TYPES,EXIT    ;yes, display signed
  1270.  
  1271. ;   ?        ( a -- )
  1272. ;        Display the contents in a memory cell.
  1273.  
  1274.         $COLON    1,'?',QUEST
  1275.         DW    AT,DOT,EXIT
  1276.  
  1277. ;; Parsing
  1278.  
  1279. ;   parse    ( b u c -- b u delta ; <string> )
  1280. ;        Scan string delimited by c. Return found string and its offset.
  1281.  
  1282.         $COLON    5,'parse',PARS
  1283.         DW    TEMP,STORE,OVER,TOR,DUPP
  1284.         DW    QBRAN,PARS8
  1285.         DW    DOLIT,1,SUBB,TEMP,AT,BLANK,EQUAL
  1286.         DW    QBRAN,PARS3
  1287.         DW    TOR
  1288. PARS1:        DW    BLANK,OVER,CAT        ;skip leading blanks ONLY
  1289.         DW    SUBB,ZLESS,INVER
  1290.         DW    QBRAN,PARS2
  1291.         DW    DOLIT,1,PLUS
  1292.         DW    DONXT,PARS1
  1293.         DW    RFROM,DROP,DOLIT,0,DUPP,EXIT
  1294. PARS2:        DW    RFROM
  1295. PARS3:        DW    OVER,SWAP
  1296.         DW    TOR
  1297. PARS4:        DW    TEMP,AT,OVER,CAT,SUBB    ;scan for delimiter
  1298.         DW    TEMP,AT,BLANK,EQUAL
  1299.         DW    QBRAN,PARS5
  1300.         DW    ZLESS
  1301. PARS5:        DW    QBRAN,PARS6
  1302.         DW    DOLIT,1,PLUS
  1303.         DW    DONXT,PARS4
  1304.         DW    DUPP,TOR
  1305.         DW    BRAN,PARS7
  1306. PARS6:        DW    RFROM,DROP,DUPP
  1307.         DW    DOLIT,1,PLUS,TOR
  1308. PARS7:        DW    OVER,SUBB
  1309.         DW    RFROM,RFROM,SUBB,EXIT
  1310. PARS8:        DW    OVER,RFROM,SUBB,EXIT
  1311.  
  1312. ;   PARSE    ( c -- b u ; <string> )
  1313. ;        Scan input stream and return counted string delimited by c.
  1314.  
  1315.         $COLON    5,'PARSE',PARSE
  1316.         DW    TOR,TIB,INN,AT,PLUS    ;current input buffer pointer
  1317.         DW    NTIB,AT,INN,AT,SUBB    ;remaining count
  1318.         DW    RFROM,PARS,INN,PSTOR,EXIT
  1319.  
  1320. ;   .(        ( -- )
  1321. ;        Output following string up to next ) .
  1322.  
  1323.         $COLON    IMEDD+2,'.(',DOTPR
  1324.         DW    DOLIT,')',PARSE,TYPES,EXIT
  1325.  
  1326. ;   (        ( -- )
  1327. ;        Ignore following string up to next ) . A comment.
  1328.  
  1329.         $COLON    IMEDD+1,'(',PAREN
  1330.         DW    DOLIT,')',PARSE,DDROP,EXIT
  1331.  
  1332. ;   \        ( -- )
  1333. ;        Ignore following text till the end of line.
  1334.  
  1335.         $COLON    IMEDD+1,'\',BKSLA
  1336.         DW    NTIB,AT,INN,STORE,EXIT
  1337.  
  1338. ;   CHAR    ( -- c )
  1339. ;        Parse next word and return its first character.
  1340.  
  1341.         $COLON    4,'CHAR',CHAR
  1342.         DW    BLANK,PARSE,DROP,CAT,EXIT
  1343.  
  1344. ;   TOKEN    ( -- a ; <string> )
  1345. ;        Parse a word from input stream and copy it to name dictionary.
  1346.  
  1347.         $COLON    5,'TOKEN',TOKEN
  1348.         DW    BLANK,PARSE,DOLIT,31,MIN
  1349.         DW    NP,AT,OVER,SUBB,CELLM
  1350.         DW    PACKS,EXIT
  1351.  
  1352. ;   WORD    ( c -- a ; <string> )
  1353. ;        Parse a word from input stream and copy it to code dictionary.
  1354.  
  1355.         $COLON    4,'WORD',WORDD
  1356.         DW    PARSE,HERE,PACKS,EXIT
  1357.  
  1358. ;; Dictionary search
  1359.  
  1360. ;   NAME>    ( na -- ca )
  1361. ;        Return a code address given a name address.
  1362.  
  1363.         $COLON    5,'NAME>',NAMET
  1364.         DW    CELLM,CELLM,AT,EXIT
  1365.  
  1366. ;   SAME?    ( a a u -- a a f \ -0+ )
  1367. ;        Compare u cells in two strings. Return 0 if identical.
  1368.  
  1369.         $COLON    5,'SAME?',SAMEQ
  1370.         DW    TOR
  1371.         DW    BRAN,SAME2
  1372. SAME1:        DW    OVER,RAT,CELLS,PLUS,AT
  1373.         DW    OVER,RAT,CELLS,PLUS,AT
  1374.         DW    SUBB,QDUP
  1375.         DW    QBRAN,SAME2
  1376.         DW    RFROM,DROP,EXIT
  1377. SAME2:        DW    DONXT,SAME1
  1378.         DW    DOLIT,0,EXIT
  1379.  
  1380. ;   find    ( a va -- ca na | a F )
  1381. ;        Search a vocabulary for a string. Return ca and na if succeeded.
  1382.  
  1383.         $COLON    4,'find',FIND
  1384.         DW    SWAP,DUPP,CAT
  1385.         DW    DOLIT,CELLL,SLASH,TEMP,STORE
  1386.         DW    DUPP,AT,TOR,CELLP,SWAP
  1387. FIND1:        DW    AT,DUPP
  1388.         DW    QBRAN,FIND6
  1389.         DW    DUPP,AT,DOLIT,MASKK,ANDD,RAT,XORR
  1390.         DW    QBRAN,FIND2
  1391.         DW    CELLP,DOLIT,-1
  1392.         DW    BRAN,FIND3
  1393. FIND2:        DW    CELLP,TEMP,AT,SAMEQ
  1394. FIND3:        DW    BRAN,FIND4
  1395. FIND6:        DW    RFROM,DROP
  1396.         DW    SWAP,CELLM,SWAP,EXIT
  1397. FIND4:        DW    QBRAN,FIND5
  1398.         DW    CELLM,CELLM
  1399.         DW    BRAN,FIND1
  1400. FIND5:        DW    RFROM,DROP,SWAP,DROP
  1401.         DW    CELLM
  1402.         DW    DUPP,NAMET,SWAP,EXIT
  1403.  
  1404. ;   NAME?    ( a -- ca na | a F )
  1405. ;        Search all context vocabularies for a string.
  1406.  
  1407.         $COLON    5,'NAME?',NAMEQ
  1408.         DW    CNTXT,DUPP,DAT,XORR
  1409.         DW    QBRAN,NAMQ1
  1410.         DW    CELLM
  1411. NAMQ1:        DW    TOR
  1412. NAMQ2:        DW    RFROM,CELLP,DUPP,TOR
  1413.         DW    AT,QDUP
  1414.         DW    QBRAN,NAMQ3
  1415.         DW    FIND,QDUP
  1416.         DW    QBRAN,NAMQ2
  1417.         DW    RFROM,DROP,EXIT
  1418. NAMQ3:        DW    RFROM,DROP
  1419.         DW    DOLIT,0,EXIT
  1420.  
  1421. ;; Terminal response
  1422.  
  1423. ;   ^H        ( bot eot cur -- bot eot cur )
  1424. ;        Backup the cursor by one character.
  1425.  
  1426.         $COLON    2,'^H',BKSP
  1427.         DW    TOR,OVER,RFROM,SWAP,OVER,XORR
  1428.         DW    QBRAN,BACK1
  1429.         DW    DOLIT,BKSPP,TECHO,ATEXE,DOLIT,1,SUBB
  1430.         DW    BLANK,TECHO,ATEXE
  1431.         DW    DOLIT,BKSPP,TECHO,ATEXE
  1432. BACK1:        DW    EXIT
  1433.  
  1434. ;   TAP        ( bot eot cur c -- bot eot cur )
  1435. ;        Accept and echo the key stroke and bump the cursor.
  1436.  
  1437.         $COLON    3,'TAP',TAP
  1438.         DW    DUPP,TECHO,ATEXE
  1439.         DW    OVER,CSTOR,DOLIT,1,PLUS,EXIT
  1440.  
  1441. ;   kTAP    ( bot eot cur c -- bot eot cur )
  1442. ;        Process a key stroke, CR or backspace.
  1443.  
  1444.         $COLON    4,'kTAP',KTAP
  1445.         DW    DUPP,DOLIT,CRR,XORR
  1446.         DW    QBRAN,KTAP2
  1447.         DW    DOLIT,BKSPP,XORR
  1448.         DW    QBRAN,KTAP1
  1449.         DW    BLANK,TAP,EXIT
  1450. KTAP1:        DW    BKSP,EXIT
  1451. KTAP2:        DW    DROP,SWAP,DROP,DUPP,EXIT
  1452.  
  1453. ;   accept    ( b u -- b u )
  1454. ;        Accept characters to input buffer. Return with actual count.
  1455.  
  1456.         $COLON    6,'accept',ACCEP
  1457.         DW    OVER,PLUS,OVER
  1458. ACCP1:        DW    DDUP,XORR
  1459.         DW    QBRAN,ACCP4
  1460.         DW    KEY,DUPP
  1461. ;        DW    BLANK,SUBB,DOLIT,95,ULESS
  1462.         DW    BLANK,DOLIT,127,WITHI
  1463.         DW    QBRAN,ACCP2
  1464.         DW    TAP
  1465.         DW    BRAN,ACCP3
  1466. ACCP2:        DW    TTAP,ATEXE
  1467. ACCP3:        DW    BRAN,ACCP1
  1468. ACCP4:        DW    DROP,OVER,SUBB,EXIT
  1469.  
  1470. ;   EXPECT    ( b u -- )
  1471. ;        Accept input stream and store count in SPAN.
  1472.  
  1473.         $COLON    6,'EXPECT',EXPEC
  1474.         DW    TEXPE,ATEXE,SPAN,STORE,DROP,EXIT
  1475.  
  1476. ;   QUERY    ( -- )
  1477. ;        Accept input stream to terminal input buffer.
  1478.  
  1479.         $COLON    5,'QUERY',QUERY
  1480.         DW    TIB,DOLIT,80,TEXPE,ATEXE,NTIB,STORE
  1481.         DW    DROP,DOLIT,0,INN,STORE,EXIT
  1482.  
  1483. ;; Error handling
  1484.  
  1485. ;   CATCH    ( ca -- 0 | err# )
  1486. ;        Execute word at ca and set up an error frame for it.
  1487.  
  1488.         $COLON    5,'CATCH',CATCH
  1489.         DW    SPAT,TOR,HANDL,AT,TOR    ;save error frame
  1490.         DW    RPAT,HANDL,STORE,EXECU    ;execute
  1491.         DW    RFROM,HANDL,STORE    ;restore error frame
  1492.         DW    RFROM,DROP,DOLIT,0,EXIT    ;no error
  1493.  
  1494. ;   THROW    ( err# -- err# )
  1495. ;        Reset system to current local error frame an update error flag.
  1496.  
  1497.         $COLON    5,'THROW',THROW
  1498.         DW    HANDL,AT,RPSTO        ;restore return stack
  1499.         DW    RFROM,HANDL,STORE    ;restore handler frame
  1500.         DW    RFROM,SWAP,TOR,SPSTO    ;restore data stack
  1501.         DW    DROP,RFROM,EXIT
  1502.  
  1503. ;   NULL$    ( -- a )
  1504. ;        Return address of a null string with zero count.
  1505.  
  1506.         $COLON    5,'NULL$',NULLS
  1507.         DW    DOVAR            ;emulate CREATE
  1508.         DW    0
  1509.         DB    99,111,121,111,116,101
  1510.  
  1511. ;   ABORT    ( -- )
  1512. ;        Reset data stack and jump to QUIT.
  1513.  
  1514.         $COLON    5,'ABORT',ABORT
  1515.         DW    NULLS,THROW
  1516.  
  1517. ;   abort"    ( f -- )
  1518. ;        Run time routine of ABORT" . Abort with a message.
  1519.  
  1520.         $COLON    COMPO+6,'abort"',ABORQ
  1521.         DW    QBRAN,ABOR1        ;text flag
  1522.         DW    DOSTR,THROW        ;pass error string
  1523. ABOR1:        DW    DOSTR,DROP,EXIT        ;drop error
  1524.  
  1525. ;; The text interpreter
  1526.  
  1527. ;   $INTERPRET    ( a -- )
  1528. ;        Interpret a word. If failed, try to convert it to an integer.
  1529.  
  1530.         $COLON    10,'$INTERPRET',INTER
  1531.         DW    NAMEQ,QDUP        ;?defined
  1532.         DW    QBRAN,INTE1
  1533.         DW    AT,DOLIT,COMPO,ANDD    ;?compile only lexicon bits
  1534.         DW    ABORQ
  1535.         DB    13,' compile only'
  1536.         DW    EXECU,EXIT        ;execute defined word
  1537. INTE1:        DW    TNUMB,ATEXE        ;convert a number
  1538.         DW    QBRAN,INTE2
  1539.         DW    EXIT
  1540. INTE2:        DW    THROW            ;error
  1541.  
  1542. ;   [        ( -- )
  1543. ;        Start the text interpreter.
  1544.  
  1545.         $COLON    IMEDD+1,'[',LBRAC
  1546.         DW    DOLIT,INTER,TEVAL,STORE,EXIT
  1547.  
  1548. ;   .OK        ( -- )
  1549. ;        Display 'ok' only while interpreting.
  1550.  
  1551.         $COLON    3,'.OK',DOTOK
  1552.         DW    DOLIT,INTER,TEVAL,AT,EQUAL
  1553.         DW    QBRAN,DOTO1
  1554.         DW    DOTQP
  1555.         DB    3,' ok'
  1556. DOTO1:        DW    CR,EXIT
  1557.  
  1558. ;   ?STACK    ( -- )
  1559. ;        Abort if the data stack underflows.
  1560.  
  1561.         $COLON    6,'?STACK',QSTAC
  1562.         DW    DEPTH,ZLESS        ;check only for underflow
  1563.         DW    ABORQ
  1564.         DB    10,' underflow',0
  1565.         DW    EXIT
  1566.  
  1567. ;   EVAL    ( -- )
  1568. ;        Interpret the input stream.
  1569.  
  1570.         $COLON    4,'EVAL',EVAL
  1571. EVAL1:        DW    TOKEN,DUPP,CAT        ;?input stream empty
  1572.         DW    QBRAN,EVAL2
  1573.         DW    TEVAL,ATEXE,QSTAC    ;evaluate input, check stack
  1574.         DW    BRAN,EVAL1
  1575. EVAL2:        DW    DROP,TPROM,ATEXE,EXIT    ;prompt
  1576.  
  1577. ;; Shell
  1578.  
  1579. ;   PRESET    ( -- )
  1580. ;        Reset data stack pointer and the terminal input buffer.
  1581.  
  1582.         $COLON    6,'PRESET',PRESE
  1583.         DW    SZERO,AT,SPSTO
  1584.         DW    DOLIT,TIBB,NTIB,CELLP,STORE,EXIT
  1585.  
  1586. ;   xio        ( a a a -- )
  1587. ;        Reset the I/O vectors 'EXPECT, 'TAP, 'ECHO and 'PROMPT.
  1588.  
  1589.         $COLON    COMPO+3,'xio',XIO
  1590.         DW    DOLIT,ACCEP,TEXPE,DSTOR
  1591.         DW    TECHO,DSTOR,EXIT
  1592.  
  1593. ;   FILE    ( -- )
  1594. ;        Select I/O vectors for file download.
  1595.  
  1596.         $COLON    4,'FILE',FILE
  1597.         DW    DOLIT,PACE,DOLIT,DROP
  1598.         DW    DOLIT,KTAP,XIO,EXIT
  1599.  
  1600. ;   HAND    ( -- )
  1601. ;        Select I/O vectors for terminal interface.
  1602.  
  1603.         $COLON    4,'HAND',HAND
  1604.         DW    DOLIT,DOTOK,DOLIT,EMIT
  1605.         DW    DOLIT,KTAP,XIO,EXIT
  1606.  
  1607. ;   I/O        ( -- a )
  1608. ;        Array to store default I/O vectors.
  1609.  
  1610.         $COLON    3,'I/O',ISLO
  1611.         DW    DOVAR            ;emulate CREATE
  1612.         DW    QRX,TXSTO        ;default I/O vectors
  1613.  
  1614. ;   CONSOLE    ( -- )
  1615. ;        Initiate terminal interface.
  1616.  
  1617.         $COLON    7,'CONSOLE',CONSO
  1618.         DW    ISLO,DAT,TQKEY,DSTOR    ;restore default I/O device
  1619.         DW    HAND,EXIT        ;keyboard input
  1620.  
  1621. ;   QUIT    ( -- )
  1622. ;        Reset return stack pointer and start text interpreter.
  1623.  
  1624.         $COLON    4,'QUIT',QUIT
  1625.         DW    RZERO,AT,RPSTO        ;reset return stack pointer
  1626. QUIT1:        DW    LBRAC            ;start interpretation
  1627. QUIT2:        DW    QUERY            ;get input
  1628.         DW    DOLIT,EVAL,CATCH,QDUP    ;evaluate input
  1629.         DW    QBRAN,QUIT2        ;continue till error
  1630.         DW    TPROM,AT,TOR        ;save input device
  1631.         DW    CONSO,NULLS,OVER,XORR    ;?display error message
  1632.         DW    QBRAN,QUIT3
  1633.         DW    SPACE,COUNT,TYPES    ;error message
  1634.         DW    DOTQP
  1635.         DB    3,' ? '            ;error prompt
  1636. QUIT3:        DW    RFROM,DOLIT,DOTOK,XORR    ;?file input
  1637.         DW    QBRAN,QUIT4
  1638.         DW    DOLIT,ERR,EMIT        ;file error, tell host
  1639. QUIT4:        DW    PRESE            ;some cleanup
  1640.         DW    BRAN,QUIT1
  1641.  
  1642. ;; The compiler
  1643.  
  1644. ;   '        ( -- ca )
  1645. ;        Search context vocabularies for the next word in input stream.
  1646.  
  1647.         $COLON    1,"'",TICK
  1648.         DW    TOKEN,NAMEQ        ;?defined
  1649.         DW    QBRAN,TICK1
  1650.         DW    EXIT            ;yes, push code address
  1651. TICK1:        DW    THROW            ;no, error
  1652.  
  1653. ;   ALLOT    ( n -- )
  1654. ;        Allocate n bytes to the code dictionary.
  1655.  
  1656.         $COLON    5,'ALLOT',ALLOT
  1657.         DW    CP,PSTOR,EXIT        ;adjust code pointer
  1658.  
  1659. ;   ,        ( w -- )
  1660. ;        Compile an integer into the code dictionary.
  1661.  
  1662.         $COLON    1,',',COMMA
  1663.         DW    HERE,DUPP,CELLP        ;cell boundary
  1664.         DW    CP,STORE,STORE,EXIT    ;adjust code pointer and compile
  1665.  
  1666. ;   [COMPILE]    ( -- ; <string> )
  1667. ;        Compile the next immediate word into code dictionary.
  1668.  
  1669.         $COLON    IMEDD+9,'[COMPILE]',BCOMP
  1670.         DW    TICK,COMMA,EXIT
  1671.  
  1672. ;   COMPILE    ( -- )
  1673. ;        Compile the next address in colon list to code dictionary.
  1674.  
  1675.         $COLON    COMPO+7,'COMPILE',COMPI
  1676.         DW    RFROM,DUPP,AT,COMMA    ;compile address
  1677.         DW    CELLP,TOR,EXIT        ;adjust return address
  1678.  
  1679. ;   LITERAL    ( w -- )
  1680. ;        Compile tos to code dictionary as an integer literal.
  1681.  
  1682.         $COLON    IMEDD+7,'LITERAL',LITER
  1683.         DW    COMPI,DOLIT,COMMA,EXIT
  1684.  
  1685. ;   $,"        ( -- )
  1686. ;        Compile a literal string up to next " .
  1687.  
  1688.         $COLON    3,'$,"',STRCQ
  1689.         DW    DOLIT,'"',WORDD        ;move string to code dictionary
  1690.         DW    COUNT,PLUS,ALGND    ;calculate aligned end of string
  1691.         DW    CP,STORE,EXIT        ;adjust the code pointer
  1692.  
  1693. ;   RECURSE    ( -- )
  1694. ;        Make the current word available for compilation.
  1695.  
  1696.         $COLON    IMEDD+7,'RECURSE',RECUR
  1697.         DW    LAST,AT,NAMET,COMMA,EXIT
  1698.  
  1699. ;; Structures
  1700.  
  1701. ;   FOR        ( -- a )
  1702. ;        Start a FOR-NEXT loop structure in a colon definition.
  1703.  
  1704.         $COLON    IMEDD+3,'FOR',FOR
  1705.         DW    COMPI,TOR,HERE,EXIT
  1706.  
  1707. ;   BEGIN    ( -- a )
  1708. ;        Start an infinite or indefinite loop structure.
  1709.  
  1710.         $COLON    IMEDD+5,'BEGIN',BEGIN
  1711.         DW    HERE,EXIT
  1712.  
  1713. ;   NEXT    ( a -- )
  1714. ;        Terminate a FOR-NEXT loop structure.
  1715.  
  1716.         $COLON    IMEDD+4,'NEXT',NEXT
  1717.         DW    COMPI,DONXT,COMMA,EXIT
  1718.  
  1719. ;   UNTIL    ( a -- )
  1720. ;        Terminate a BEGIN-UNTIL indefinite loop structure.
  1721.  
  1722.         $COLON    IMEDD+5,'UNTIL',UNTIL
  1723.         DW    COMPI,QBRAN,COMMA,EXIT
  1724.  
  1725. ;   AGAIN    ( a -- )
  1726. ;        Terminate a BEGIN-AGAIN infinite loop structure.
  1727.  
  1728.         $COLON    IMEDD+5,'AGAIN',AGAIN
  1729.         DW    COMPI,BRAN,COMMA,EXIT
  1730.  
  1731. ;   IF        ( -- A )
  1732. ;        Begin a conditional branch structure.
  1733.  
  1734.         $COLON    IMEDD+2,'IF',IFF
  1735.         DW    COMPI,QBRAN,HERE
  1736.         DW    DOLIT,0,COMMA,EXIT
  1737.  
  1738. ;   AHEAD    ( -- A )
  1739. ;        Compile a forward branch instruction.
  1740.  
  1741.         $COLON    IMEDD+5,'AHEAD',AHEAD
  1742.         DW    COMPI,BRAN,HERE,DOLIT,0,COMMA,EXIT
  1743.  
  1744. ;   REPEAT    ( A a -- )
  1745. ;        Terminate a BEGIN-WHILE-REPEAT indefinite loop.
  1746.  
  1747.         $COLON    IMEDD+6,'REPEAT',REPEA
  1748.         DW    AGAIN,HERE,SWAP,STORE,EXIT
  1749.  
  1750. ;   THEN    ( A -- )
  1751. ;        Terminate a conditional branch structure.
  1752.  
  1753.         $COLON    IMEDD+4,'THEN',THENN
  1754.         DW    HERE,SWAP,STORE,EXIT
  1755.  
  1756. ;   AFT        ( a -- a A )
  1757. ;        Jump to THEN in a FOR-AFT-THEN-NEXT loop the first time through.
  1758.  
  1759.         $COLON    IMEDD+3,'AFT',AFT
  1760.         DW    DROP,AHEAD,BEGIN,SWAP,EXIT
  1761.  
  1762. ;   ELSE    ( A -- A )
  1763. ;        Start the false clause in an IF-ELSE-THEN structure.
  1764.  
  1765.         $COLON    IMEDD+4,'ELSE',ELSEE
  1766.         DW    AHEAD,SWAP,THENN,EXIT
  1767.  
  1768. ;   WHILE    ( a -- A a )
  1769. ;        Conditional branch out of a BEGIN-WHILE-REPEAT loop.
  1770.  
  1771.         $COLON    IMEDD+5,'WHILE',WHILE
  1772.         DW    IFF,SWAP,EXIT
  1773.  
  1774. ;   ABORT"    ( -- ; <string> )
  1775. ;        Conditional abort with an error message.
  1776.  
  1777.         $COLON    IMEDD+6,'ABORT"',ABRTQ
  1778.         DW    COMPI,ABORQ,STRCQ,EXIT
  1779.  
  1780. ;   $"        ( -- ; <string> )
  1781. ;        Compile an inline string literal.
  1782.  
  1783.         $COLON    IMEDD+2,'$"',STRQ
  1784.         DW    COMPI,STRQP,STRCQ,EXIT
  1785.  
  1786. ;   ."        ( -- ; <string> )
  1787. ;        Compile an inline string literal to be typed out at run time.
  1788.  
  1789.         $COLON    IMEDD+2,'."',DOTQ
  1790.         DW    COMPI,DOTQP,STRCQ,EXIT
  1791.  
  1792. ;; Name compiler
  1793.  
  1794. ;   ?UNIQUE    ( a -- a )
  1795. ;        Display a warning message if the word already exists.
  1796.  
  1797.         $COLON    7,'?UNIQUE',UNIQU
  1798.         DW    DUPP,NAMEQ        ;?name exists
  1799.         DW    QBRAN,UNIQ1
  1800.         DW    DOTQP            ;redefinitions are OK
  1801.         DB    7,' reDef '        ;but the user should be warned
  1802.         DW    OVER,COUNT,TYPES    ;just in case its not planned
  1803. UNIQ1:        DW    DROP,EXIT
  1804.  
  1805. ;   $,n        ( na -- )
  1806. ;        Build a new dictionary name using the string at na.
  1807.  
  1808.         $COLON    3,'$,n',SNAME
  1809.         DW    DUPP,CAT        ;?null input
  1810.         DW    QBRAN,PNAM1
  1811.         DW    UNIQU            ;?redefinition
  1812.         DW    DUPP,LAST,STORE        ;save na for vocabulary link
  1813.         DW    HERE,ALGND,SWAP        ;align code address
  1814.         DW    CELLM            ;link address
  1815.         DW    CRRNT,AT,AT,OVER,STORE
  1816.         DW    CELLM,DUPP,NP,STORE    ;adjust name pointer
  1817.         DW    STORE,EXIT        ;save code pointer
  1818. PNAM1:        DW    STRQP
  1819.         DB    5,' name'        ;null input
  1820.         DW    THROW
  1821.  
  1822. ;; FORTH compiler
  1823.  
  1824. ;   $COMPILE    ( a -- )
  1825. ;        Compile next word to code dictionary as a token or literal.
  1826.  
  1827.         $COLON    8,'$COMPILE',SCOMP
  1828.         DW    NAMEQ,QDUP        ;?defined
  1829.         DW    QBRAN,SCOM2
  1830.         DW    AT,DOLIT,IMEDD,ANDD    ;?immediate
  1831.         DW    QBRAN,SCOM1
  1832.         DW    EXECU,EXIT        ;its immediate, execute
  1833. SCOM1:        DW    COMMA,EXIT        ;its not immediate, compile
  1834. SCOM2:        DW    TNUMB,ATEXE        ;try to convert to number
  1835.         DW    QBRAN,SCOM3
  1836.         DW    LITER,EXIT        ;compile number as integer
  1837. SCOM3:        DW    THROW            ;error
  1838.  
  1839. ;   OVERT    ( -- )
  1840. ;        Link a new word into the current vocabulary.
  1841.  
  1842.         $COLON    5,'OVERT',OVERT
  1843.         DW    LAST,AT,CRRNT,AT,STORE,EXIT
  1844.  
  1845. ;   ;        ( -- )
  1846. ;        Terminate a colon definition.
  1847.  
  1848.         $COLON    IMEDD+COMPO+1,';',SEMIS
  1849.         DW    COMPI,EXIT,LBRAC,OVERT,EXIT
  1850.  
  1851. ;   ]        ( -- )
  1852. ;        Start compiling the words in the input stream.
  1853.  
  1854.         $COLON    1,']',RBRAC
  1855.         DW    DOLIT,SCOMP,TEVAL,STORE,EXIT
  1856.  
  1857. ;   call,    ( ca -- )
  1858. ;        Assemble a call instruction to ca.
  1859.  
  1860.         $COLON    5,'call,',CALLC
  1861.         DW    DOLIT,CALLL,COMMA,HERE    ;Direct Threaded Code
  1862.         DW    CELLP,SUBB,COMMA,EXIT    ;DTC 8086 relative call
  1863.  
  1864. ;   :        ( -- ; <string> )
  1865. ;        Start a new colon definition using next word as its name.
  1866.  
  1867.         $COLON    1,':',COLON
  1868.         DW    TOKEN,SNAME,DOLIT,DOLST
  1869.         DW    CALLC,RBRAC,EXIT
  1870.  
  1871. ;   IMMEDIATE    ( -- )
  1872. ;        Make the last compiled word an immediate word.
  1873.  
  1874.         $COLON    9,'IMMEDIATE',IMMED
  1875.         DW    DOLIT,IMEDD,LAST,AT,AT,ORR
  1876.         DW    LAST,AT,STORE,EXIT
  1877.  
  1878. ;; Defining words
  1879.  
  1880. ;   USER    ( u -- ; <string> )
  1881. ;        Compile a new user variable.
  1882.  
  1883.         $COLON    4,'USER',USER
  1884.         DW    TOKEN,SNAME,OVERT
  1885.         DW    DOLIT,DOLST,CALLC
  1886.         DW    DOLIT,DOUSE,COMMA
  1887.         DW    COMMA,EXIT
  1888.  
  1889. ;   CREATE    ( -- ; <string> )
  1890. ;        Compile a new array entry without allocating code space.
  1891.  
  1892.         $COLON    6,'CREATE',CREAT
  1893.         DW    TOKEN,SNAME,OVERT
  1894.         DW    DOLIT,DOLST,CALLC
  1895.         DW    DOLIT,DOVAR,COMMA,EXIT
  1896.  
  1897. ;   VARIABLE    ( -- ; <string> )
  1898. ;        Compile a new variable initialized to 0.
  1899.  
  1900.         $COLON    8,'VARIABLE',VARIA
  1901.         DW    CREAT,DOLIT,0,COMMA,EXIT
  1902.  
  1903. ;; Tools
  1904.  
  1905. ;   _TYPE    ( b u -- )
  1906. ;        Display a string. Filter non-printing characters.
  1907.  
  1908.         $COLON    5,'_TYPE',UTYPE
  1909.         DW    TOR            ;start count down loop
  1910.         DW    BRAN,UTYP2        ;skip first pass
  1911. UTYP1:        DW    DUPP,CAT,TCHAR,EMIT    ;display only printable
  1912.         DW    DOLIT,1,PLUS        ;increment address
  1913. UTYP2:        DW    DONXT,UTYP1        ;loop till done
  1914.         DW    DROP,EXIT
  1915.  
  1916. ;   dm+        ( a u -- a )
  1917. ;        Dump u bytes from , leaving a+u on the stack.
  1918.  
  1919.         $COLON    3,'dm+',DUMPP
  1920.         DW    OVER,DOLIT,4,UDOTR    ;display address
  1921.         DW    SPACE,TOR        ;start count down loop
  1922.         DW    BRAN,PDUM2        ;skip first pass
  1923. PDUM1:        DW    DUPP,CAT,DOLIT,3,UDOTR    ;display numeric data
  1924.         DW    DOLIT,1,PLUS        ;increment address
  1925. PDUM2:        DW    DONXT,PDUM1        ;loop till done
  1926.         DW    EXIT
  1927.  
  1928. ;   DUMP    ( a u -- )
  1929. ;        Dump u bytes from a, in a formatted manner.
  1930.  
  1931.         $COLON    4,'DUMP',DUMP
  1932.         DW    BASE,AT,TOR,HEX        ;save radix, set hex
  1933.         DW    DOLIT,16,SLASH        ;change count to lines
  1934.         DW    TOR            ;start count down loop
  1935. DUMP1:        DW    CR,DOLIT,16,DDUP,DUMPP    ;display numeric
  1936.         DW    ROT,ROT
  1937.         DW    DOLIT,2,SPACS,UTYPE    ;display printable characters
  1938.         DW    NUFQ,INVER        ;user control
  1939.         DW    QBRAN,DUMP2
  1940.         DW    DONXT,DUMP1        ;loop till done
  1941.         DW    BRAN,DUMP3
  1942. DUMP2:        DW    RFROM,DROP        ;cleanup loop stack, early exit
  1943. DUMP3:        DW    DROP,RFROM,BASE,STORE    ;restore radix
  1944.         DW    EXIT
  1945.  
  1946. ;   .S        ( ... -- ... )
  1947. ;        Display the contents of the data stack.
  1948.  
  1949.         $COLON    2,'.S',DOTS
  1950.         DW    CR,DEPTH        ;stack depth
  1951.         DW    TOR            ;start count down loop
  1952.         DW    BRAN,DOTS2        ;skip first pass
  1953. DOTS1:        DW    RAT,PICK,DOT        ;index stack, display contents
  1954. DOTS2:        DW    DONXT,DOTS1        ;loop till done
  1955.         DW    DOTQP
  1956.         DB    4,' <sp',0
  1957.         DW    EXIT
  1958.  
  1959. ;   !CSP    ( -- )
  1960. ;        Save stack pointer in CSP for error checking.
  1961.  
  1962.         $COLON    4,'!CSP',STCSP
  1963.         DW    SPAT,CSP,STORE,EXIT    ;save pointer
  1964.  
  1965. ;   ?CSP    ( -- )
  1966. ;        Abort if stack pointer differs from that saved in CSP.
  1967.  
  1968.         $COLON    4,'?CSP',QCSP
  1969.         DW    SPAT,CSP,AT,XORR    ;compare pointers
  1970.         DW    ABORQ            ;abort if different
  1971.         DB    6,'stacks',0
  1972.         DW    EXIT
  1973.  
  1974. ;   >NAME    ( ca -- na | F )
  1975. ;        Convert code address to a name address.
  1976.  
  1977.         $COLON    5,'>NAME',TNAME
  1978.         DW    CRRNT            ;vocabulary link
  1979. TNAM1:        DW    CELLP,AT,QDUP        ;check all vocabularies
  1980.         DW    QBRAN,TNAM4
  1981.         DW    DDUP
  1982. TNAM2:        DW    AT,DUPP            ;?last word in a vocabulary
  1983.         DW    QBRAN,TNAM3
  1984.         DW    DDUP,NAMET,XORR        ;compare
  1985.         DW    QBRAN,TNAM3
  1986.         DW    CELLM            ;continue with next word
  1987.         DW    BRAN,TNAM2
  1988. TNAM3:        DW    SWAP,DROP,QDUP
  1989.         DW    QBRAN,TNAM1
  1990.         DW    SWAP,DROP,SWAP,DROP,EXIT
  1991. TNAM4:        DW    DROP,DOLIT,0,EXIT
  1992.  
  1993. ;   .ID        ( na -- )
  1994. ;        Display the name at address.
  1995.  
  1996.         $COLON    3,'.ID',DOTID
  1997.         DW    QDUP            ;if zero no name
  1998.         DW    QBRAN,DOTI1
  1999.         DW    COUNT,DOLIT,01FH,ANDD    ;mask lexicon bits
  2000.         DW    UTYPE,EXIT        ;display name string
  2001. DOTI1:        DW    DOTQP
  2002.         DB    9,' {noName}'
  2003.         DW    EXIT
  2004.  
  2005. ;   SEE        ( -- ; <string> )
  2006. ;        A simple decompiler.
  2007.  
  2008.         $COLON    3,'SEE',SEE
  2009.         DW    TICK            ;starting address
  2010.         DW    CR,CELLP
  2011. SEE1:        DW    CELLP,DUPP,AT,DUPP    ;?does it contain a zero
  2012.         DW    QBRAN,SEE2
  2013.         DW    TNAME            ;?is it a name
  2014. SEE2:        DW    QDUP            ;name address or zero
  2015.         DW    QBRAN,SEE3
  2016.         DW    SPACE,DOTID        ;display name
  2017.         DW    BRAN,SEE4
  2018. SEE3:        DW    DUPP,AT,UDOT        ;display number
  2019. SEE4:        DW    NUFQ            ;user control
  2020.         DW    QBRAN,SEE1
  2021.         DW    DROP,EXIT
  2022.  
  2023. ;   WORDS    ( -- )
  2024. ;        Display the names in the context vocabulary.
  2025.  
  2026.         $COLON    5,'WORDS',WORDS
  2027.         DW    CR,CNTXT,AT        ;only in context
  2028. WORS1:        DW    AT,QDUP            ;?at end of list
  2029.         DW    QBRAN,WORS2
  2030.         DW    DUPP,SPACE,DOTID    ;display a name
  2031.         DW    CELLM,NUFQ        ;user control
  2032.         DW    QBRAN,WORS1
  2033.         DW    DROP
  2034. WORS2:        DW    EXIT
  2035.  
  2036. ;; Hardware reset
  2037.  
  2038. ;   VER        ( -- n )
  2039. ;        Return the version number of this implementation.
  2040.  
  2041.         $COLON    3,'VER',VERSN
  2042.         DW    DOLIT,VER*256+EXT,EXIT
  2043.  
  2044. ;   hi        ( -- )
  2045. ;        Display the sign-on message of eForth.
  2046.  
  2047.         $COLON    2,'hi',HI
  2048.         DW    STOIO,CR,DOTQP        ;initialize I/O
  2049.         DB    11,'eForth v'        ;model
  2050.         DB    VER+'0','.',EXT+'0'    ;version
  2051.         DW    CR,EXIT
  2052.  
  2053. ;   'BOOT    ( -- a )
  2054. ;        The application startup vector.
  2055.  
  2056.         $COLON    5,"'BOOT",TBOOT
  2057.         DW    DOVAR
  2058.         DW    HI            ;application to boot
  2059.  
  2060. ;   COLD    ( -- )
  2061. ;        The hilevel cold start sequence.
  2062.  
  2063.         $COLON    4,'COLD',COLD
  2064. COLD1:        DW    DOLIT,UZERO,DOLIT,UPP
  2065.         DW    DOLIT,ULAST-UZERO,CMOVE    ;initialize user area
  2066.         DW    PRESE            ;initialize data stack and TIB
  2067.         DW    TBOOT,ATEXE        ;application boot
  2068.         DW    FORTH,CNTXT,AT,DUPP    ;initialize search order
  2069.         DW    CRRNT,DSTOR,OVERT
  2070.         DW    QUIT            ;start interpretation
  2071.         DW    BRAN,COLD1        ;just in case
  2072.  
  2073. ;===============================================================
  2074.  
  2075. LASTN        EQU    _NAME+4            ;last name address in name dictionary
  2076.  
  2077. NTOP        EQU    _NAME-0            ;next available memory in name dictionary
  2078. CTOP        EQU    $+0            ;next available memory in code dictionary
  2079.  
  2080. MAIN        ENDS
  2081.  
  2082. END    ORIG
  2083.  
  2084. ;===============================================================
  2085.  
  2086.