1 // s5 - data stack pointer
2 // s6 - return stack pointer
3 // s7 - program counter
15 .macro def name, namelen, label, prev, flags=0
19 .type name_\label, @object
22 .byte \flags + \namelen
24 .skip (8 - ((\namelen + 1) & 7)) & 7
30 .macro defword name, namelen, label, prev, flags=0
31 def "\name", \namelen, \label, \prev, \flags
35 .macro defcode name, namelen, label, prev, flags=0
36 def "\name", \namelen, \label, \prev, \flags
44 .macro defvar name, namelen, label, prev, initial=0, flags=0
45 defcode \name, \namelen, \label, \prev, \flags
55 .macro defconst name, namelen, label, prev, value, flags=0
56 defcode \name, \namelen, \label, \prev, \flags
107 .type DOCOL, @function
115 .type main, @function
147 .size return, . - return
225 .size _WORD, . - _WORD
229 .size _EMIT, . - _EMIT
235 defcode "DONE", 4, DONE, 0
239 defcode "EXIT", 4, EXIT, DONE
243 defcode "DROP", 4, DROP, EXIT
247 defword "2DROP", 5, TDROP, DROP
252 defcode "SWAP", 4, SWAP, TDROP
259 defcode "OVER", 4, OVER, SWAP
264 // ( X Y Z -- Z X Y )
265 defcode "ROT", 3, ROT, OVER
274 // ( X Y Z -- Y Z X )
275 // ( Z X Y ) -- ( X Y Z )
276 defcode "-ROT", 4, NROT, ROT
285 defcode "DUP", 3, DUP, NROT
290 defcode "2DUP", 3, TDUP, DUP
297 defcode "?DUP", 4, QDUP, TDUP
304 defword "1+", 2, INC, QDUP
309 defword "1-", 2, DEC, INC
314 defcode "+", 1, ADD, DEC
321 defcode "-", 1, SUB, ADD
328 defcode "*", 1, MUL, SUB
335 defcode "AND", 3, AND, MUL
342 defcode "OR", 2, OR, AND
349 defcode "XOR", 3, XOR, OR
356 defcode "RSHIFT", 6, RSHIFT, XOR
363 defcode "0=", 2, EQZ, RSHIFT
375 defword "=", 1, EQ, EQZ
381 defcode "<", 1, LT, EQ
388 defword ">", 1, GT, LT
393 defcode "KEY", 3, KEY, GT
398 // ( -- word wordlen )
399 defcode "WORD", 4, WORD, KEY
405 // ( s1 s2 len -- eql )
406 defword "MEMEQ", 5, MEMEQ, WORD
407 .quad ROT // ( len s1 s2 )
408 .quad DUP // ( len len s1 s2 )
409 GOTOZ 4f // ( len s1 s2 )
411 .quad TOR // ( s1 s2 -- len )
413 1: // ( s1 s2 -- len )
414 .quad DUP // ( s1 s1 s2 -- len )
415 .quad FETCHBYTE // ( c1 s1 s2 -- len )
416 .quad TOR // ( s1 s2 -- c1 len )
417 .quad SWAP // ( s2 s1 -- c1 len )
418 .quad DUP // ( s2 s2 s1 -- c1 len )
419 .quad FETCHBYTE // ( c2 s2 s1 -- c1 len )
420 .quad FROMR // ( c1 c2 s2 s1 -- len )
421 .quad SUB // ( eql s2 s1 -- len )
422 GOTONZ 3f // ( s2 s1 -- len )
424 .quad FROMR // ( len s2 s1 )
425 .quad DEC // ( len-1 s2 s1 )
426 .quad DUP // ( len-1 len-1 s2 s1 )
427 GOTOZ 4f // ( len-1 s2 s1 )
429 .quad TOR // ( s2 s1 -- len-1 )
430 .quad INC // ( s2+1 s1 -- len-1 )
431 .quad SWAP // ( s1 s2+1 -- len-1 )
432 .quad INC // ( s1+1 s2+1 -- len-1 )
436 3: // not equal // ( s2 s1 -- len )
437 .quad FROMR // ( len s2 s1 )
438 .quad TDROP // ( s1 )
440 .quad LIT, 0 // ( 0 )
443 4: // equal // ( len s2 s1 )
444 .quad TDROP // ( s1 )
446 .quad LIT, -1 // ( 0 )
449 // ( name namelen -- &word )
450 defword "FIND", 4, FIND, MEMEQ
451 .quad TOR // ( namelen -- name )
452 .quad TOR // ( -- namelen name )
453 .quad LATEST // ( &LATEST -- namelen name )
454 .quad FETCH // ( LATEST -- namelen name )
456 1: // ( &word -- namelen name )
457 .quad DUP // ( &word &word -- namelen name )
458 .quad LIT, 8 // ( 8 &word &word -- namelen name )
459 .quad ADD // ( &flags &word -- namelen name )
460 .quad FETCHBYTE // ( flags &word -- namelen name )
461 .quad DUP // ( flags flags &word -- namelen name )
462 .quad LIT, F_HIDDEN // ( F_HIDDEN flags flags &word -- namelen name )
463 .quad AND // ( hidden flags &word -- namelen name )
464 GOTONZ 4f // ( flags &word -- namelen name )
465 .quad LIT, F_LENMASK // ( F_LENMASK flags &word -- namelen name )
466 .quad AND // ( len &word -- namelen name )
467 .quad RSPFETCH // ( RSP len &word -- namelen name )
468 .quad FETCH // ( namelen len &word -- namelen name )
469 .quad SUB // ( eql &word -- namelen name )
470 GOTONZ 2f // ( &word -- namelen name )
472 .quad DUP // ( &word &word -- namelen name )
473 .quad LIT, 9 // ( 9 &word &word -- namelen name )
474 .quad ADD // ( &wname &word -- namelen name )
476 .quad RSPFETCH // ( &namelen wname &word -- namelen name )
477 .quad FETCH // ( namelen wname &word -- namelen name )
478 .quad SWAP // ( &wname namelen &word -- namelen name )
479 .quad RSPFETCH // ( RSP wname namelen &word -- namelen name )
480 .quad LIT, 8 // ( 8 RSP wname namelen &word -- namelen name )
481 .quad ADD // ( &name wname namelen &word -- namelen name )
482 .quad FETCH // ( name wname namelen &word -- namelen name )
483 .quad MEMEQ // ( eql &word -- namelen name )
484 GOTOZ 2f // ( &word -- namelen name )
487 .quad RDROP // ( &word -- name )
488 .quad RDROP // ( &word )
489 .quad EXIT // noreturn
491 4: // hidden // ( flags &word -- namelen name )
492 .quad DROP // ( &word -- namelen name )
494 2: // hidden or not equal // ( &word -- namelen name )
495 .quad FETCH // ( &next -- namelen name )
496 .quad DUP // ( &next &next -- namelen name )
497 GOTONZ 1b // ( &next -- namelen name )
498 GOTO 3b // ( 0 -- namelen name )
500 defcode "BRANCH", 6, BRANCH, FIND
505 defcode "0BRANCH", 7, ZBRANCH, BRANCH
507 beq a0, zero, code_BRANCH
511 defcode ">R", 2, TOR, ZBRANCH
516 defcode "R>", 2, FROMR, TOR
521 defcode "RSP!", 4, RSPSTORE, FROMR
525 defcode "RSP@", 4, RSPFETCH, RSPSTORE
529 defcode "RDROP", 5, RDROP, RSPFETCH
533 defcode "DSP!", 4, DSPSTORE, RDROP
537 defcode "DSP@", 4, DSPFETCH, DSPSTORE
542 // ( src dest len -- )
543 defword "CMOVE", 5, CMOVE, DSPFETCH
546 .quad ROT // ( len src dest )
547 .quad DUP // ( len len src dest )
548 GOTOZ 2f // ( len src dest )
549 .quad NROT // ( src dest len )
550 .quad TDUP // ( src dest src dest len )
551 .quad FETCHBYTE // ( byte dest src dest len )
552 .quad SWAP // ( dest byte src dest len )
553 .quad STORE // ( src dest len )
554 .quad INC // ( src+1 dest len )
555 .quad NROT // ( dest len src+1 )
556 .quad INC // ( dest+1 len src+1 )
557 .quad NROT // ( len src+1 dest+1 )
558 .quad DEC // ( len-1 src+1 dest+1 )
559 .quad NROT // ( src+1 dest+1 len-1 )
562 2: // ( len src dest )
563 .quad TDROP // ( dest )
567 // ( name namelen -- )
568 defword "CREATE", 6, CREATE, CMOVE
569 // store the link pointer
603 .quad HERE // ( &HERE namelen )
604 .quad DUP // ( &HERE &HERE namelen )
605 .quad FETCH // ( HERE &HERE namelen )
606 .quad ROT // ( namelen HERE &HERE )
607 .quad ADD // ( newHERE &HERE )
608 .quad LIT, 7 // ( 7 newHERE &HERE )
609 .quad ADD // ( newHERE &HERE)
610 .quad LIT, ~7 // ( ~7 newHERE &HERE )
611 .quad AND // ( newHERE &HERE )
612 .quad SWAP // ( &HERE newHERE )
617 // ( str len -- err val )
618 defword "NUMBER", 6, NUMBER, CREATE
619 .quad OVER // ( len str len )
620 GOTOZ 1f // ( str len )
622 .quad DUP // ( str str len )
623 .quad FETCHBYTE // ( ch str len )
624 .quad LIT, '-' // ( '-' ch str len )
625 .quad EQ // ( eql str len )
626 GOTOZ 2f // ( str len )
628 .quad LIT, -1 // ( -1 str len )
629 .quad TOR // ( str len -- -1 )
630 .quad INC // ( str+1 len -- -1 )
631 .quad SWAP // ( len str+1 -- -1 )
632 .quad DEC // ( len-1 str+1 -- -1 )
633 .quad SWAP // ( str+1 len -- -1 )
634 .quad OVER // ( len str+1 len -- -1 )
635 .quad EQZ // ( !len str+1 len -- -1 )
636 GOTOZ 3f // ( str+1 len -- -1 )
638 .quad RDROP // ( str len )
642 .quad LIT, 1 // ( 1 str len )
643 .quad TOR // ( str len -- 1 )
646 .quad LIT, 0 // ( 0 str len -- neg )
647 .quad TOR // ( str len -- 0 neg )
649 4: // ( str len -- 0 neg )
650 .quad DUP // ( str str len -- val neg )
651 .quad FETCHBYTE // ( ch str len -- val neg )
652 .quad LIT, '0' // ( '0' ch str len -- val neg )
653 .quad OVER // ( ch '0' ch str len -- val neg )
654 .quad LT // ( lt ch str len -- val neg )
655 GOTONZ 5f // ( ch str len -- val neg )
657 // ( ch str len -- val neg )
658 .quad DUP // ( ch ch str len -- val neg )
659 .quad LIT, '9' // ( '9' ch ch str len -- val neg )
660 .quad LT // ( lt ch str len -- val neg )
661 GOTONZ 5f // ( ch str len -- val neg )
663 .quad LIT, '0' // ( '0' ch str len -- val neg )
664 .quad SUB // ( dig str len -- val neg )
665 .quad FROMR // ( val dig str len -- neg )
666 .quad LIT, 10 // ( 10 val dig str len -- neg )
667 .quad MUL // ( val dig str len -- neg )
668 .quad ADD // ( val str len -- neg )
669 .quad TOR // ( str len -- val neg )
671 .quad INC // ( str+1 len -- val neg )
672 .quad SWAP // ( len str+1 -- val neg )
673 .quad DEC // ( len-1 str+1 -- val neg )
674 .quad SWAP // ( str+1 len-1 -- val neg )
675 .quad OVER // ( len-1 str+1 len-1 -- val neg )
676 GOTONZ 4b // ( str+1 len-1 -- val neg )
678 .quad TDROP // ( -- val neg )
679 .quad FROMR // ( val -- neg )
680 .quad FROMR // ( neg val )
682 .quad LIT, -1 // ( -1 val )
685 5: // invalid char ( ch str len -- val neg )
686 .quad DROP // ( str len -- val neg )
687 .quad RDROP // ( str len -- neg )
688 .quad RDROP // ( str len )
691 1: // empty string ( str len )
693 .quad LIT, 0 // ( 0 )
695 .quad EXIT // noreturn
698 defcode "ERROR", 5, ERROR, NUMBER
704 defcode "TELL", 4, TELL, ERROR
711 defcode "ENTER", 5, ENTER, TELL
716 defword "INTERPRET", 9, INTERPRET, ENTER
717 .quad WORD // ( word wordlen )
720 .quad OVER // ( wordlen word wordlen )
721 .quad EQZ // ( wordlen==0 word wordlen )
722 GOTOZ 1f // ( word wordlen )
723 .quad LIT, 0 // ( 0 )
724 .quad DONE // noreturn
726 1: // find word in dictionary
727 .quad TDUP // ( name namelen name namelen )
728 .quad FIND // ( word name namelen )
731 .quad DUP // ( word word name namelen )
732 GOTOZ 2f // ( word name namelen )
735 .quad TOR // ( name namelen -- word )
736 .quad TDROP // ( -- word )
737 .quad FROMR // ( word )
739 // check if word is immediate
740 .quad DUP // ( word word )
741 .quad LIT, 8 // ( 8 word word )
742 .quad ADD // ( word+8 word )
743 .quad FETCHBYTE // ( nf word )
744 .quad LIT, F_IMMED // ( F_IMMED nf word )
745 .quad AND // ( imm word )
746 .quad EQZ // ( !imm word )
749 // check if were compiling
750 .quad STATE, FETCH // ( state word )
753 .quad TCFA // ( *cw )
755 .quad EXIT // noreturn
758 .quad TCFA // ( &cw )
759 .quad ENTER // noreturn
762 2: // not found, maybe number ( word name namelen )
763 .quad DROP // ( name namelen )
764 .quad NUMBER // ( err value )
765 GOTOZ 4f // ( value )
767 .quad STATE, FETCH // ( imm value )
768 GOTOZ 5f // ( value )
771 .quad LIT, LIT // ( LIT value )
772 .quad COMMA // ( value )
774 .quad EXIT // noreturn
777 .quad EXIT // ( value ), noreturn
781 .quad ERROR // noreturn
783 defword "QUIT", 4, QUIT, INTERPRET
788 defcode "!", 1, STORE, QUIT
794 defcode "@", 1, FETCH, STORE
800 defcode "C!", 2, STOREBYTE, FETCH
806 defcode "C@", 2, FETCHBYTE, STOREBYTE
812 defcode ".", 1, PRINT, FETCHBYTE
819 defword ",", 1, COMMA, PRINT
820 .quad HERE // ( &HERE word )
821 .quad SWAP // ( word &HERE )
822 .quad OVER // ( &HERE word &HERE )
823 .quad FETCH // ( HERE word &HERE )
824 .quad SWAP // ( word HERE &HERE )
825 .quad OVER // ( HERE word HERE &HERE )
826 .quad STORE // ( HERE &HERE )
827 .quad LIT, 8 // ( 8 HERE &HERE )
828 .quad ADD // ( HERE+8 &HERE )
829 .quad SWAP // ( &HERE HERE+8 )
831 .quad EXIT // noreturn
833 defcode "'", 1, TICK, COMMA
839 defword "[']", 3, BTICK, TICK, F_IMMED
845 defword "[", 1, LBRACK, BTICK, F_IMMED
851 defword "]", 1, RBRACK, LBRACK
857 defword "HIDDEN", 6, HIDDEN, RBRACK
868 defword "HIDE", 4, HIDE, HIDDEN
873 defword "IMMEDIATE", 9, IMMEDIATE, HIDE
885 defcode "LIT", 3, LIT, IMMEDIATE
891 defword ":", 1, COLON, LIT
894 .quad LIT, DOCOL, COMMA
895 .quad LATEST, FETCH, HIDDEN
899 defword ";", 1, SEMICOLON, COLON, F_IMMED
900 .quad LIT, EXIT, COMMA
901 .quad LATEST, FETCH, HIDDEN
905 defcode "EXECUTE", 7, EXECUTE, SEMICOLON
909 defcode "EMIT", 4, EMIT, EXECUTE
914 defcode "CHAR", 4, CHAR, EMIT
921 defword "TCFA", 4, TCFA, CHAR
922 .quad LIT, 8 // ( 8 word )
923 .quad ADD // ( &flags )
924 .quad DUP // ( &flags &flags )
925 .quad FETCHBYTE // ( flags &flags )
926 .quad LIT, F_LENMASK // ( F_LENMASK flags &flags )
927 .quad AND // ( len &flags )
929 .quad LIT, 8 // ( 8 ptr )
931 .quad LIT, ~7 // ( ~7 ptr )
935 defword "RECURSE", 7, RECURSE, TCFA, F_IMMED
941 defvar "LATEST", 6, LATEST, RECURSE, name_R0
942 defvar "HERE", 4, HERE, LATEST, memory
943 defvar "STATE", 5, STATE, HERE
944 defvar "S0", 2, S0, STATE
945 defconst "R0", 2, R0, S0, return_stack