I originally wrote this on the x86 16-bit following the roadmap in the Byte book on Threaded Interpretive Languages:
656 ;-----------------------------------------------------------------------------
657 ;
658 ; Inner interpreter implementation
659 ;
660 00E5 CODE ends
661 0000 DICT segment
662
663 ;
664 ; SEMI does not have a header, but has a standard word address
665 ;
666 0000 00E5r _SEMI dw offset SEMI
Turbo Assembler Version 3.2 05/06/15 15:45:56 Page 10
tilli.ASM
TILLI.ASM - Threaded Interpretive Language Little Implementation
667
668 0002 DICT ends
669 00E5 CODE segment
670
671 00E5 SEMI:
672 public SEMI
673 00E5 8B 76 00 mov SI,[BP] ; Pop return address
674 00E8 83 C5 02 add BP,2
675
676 00EB NEXT:
677 public NEXT
678 00EB 8B 3C mov DI,[SI] ; Get next word address
679 00ED 83 C6 02 add SI,2
680
681 00F0 RUN:
682 public RUN
683 00F0 8B 1D mov BX,[DI] ; Run a threaded word
684 00F2 83 C7 02 add DI,2
685 00F5 FF E3 jmp BX
686
687 00F7 __COLON:
688 public __COLON
689 00F7 83 ED 02 sub BP,2 ; Push instruction register
690 00FA 89 76 00 mov [BP],SI
691 00FD 8B F7 mov SI,DI ; Point to nested secondary
692 00FF EB EA jmp short NEXT
693
694
695 ;-----------------------------------------------------------------------------
696 ;
697 ; EXECUTE ( addr -- )
698 ;
699 ; Execute dictionary entry at compilation address on stack; for example,
700 ; address returned by FIND.
701 ;
702 0101 CODE ends
703 0002 DICT segment
704
705 header <'EXECUTE'>
1 706 0002 0000 dw PREV_ENTRY
1 707 0004 07 db offset ??0007 - offset $ - 1 ; the 'EXECUTE' length
1 708 0005 45 58 45 43 55 54 45 db 'EXECUTE'
1 709 000C ??0007 label byte
710
711 000C 0101r _EXECUTE dw offset __EXECUTE
712
713 000E DICT ends
714 0101 CODE segment
715
716 0101 __EXECUTE:
717 0101 5F pop DI ; Get word address of the word
718 0102 EB EC jmp Run
From there, I ported it to the 6800;
00532 ;=== < Inner interpreter >====================================================
00533
00534 ;-----------------------------------------------------------------------------
00535 ;
00536 ; SEMI does not have a header, but has a standard word address
00537 ;
016E 0170 00538 _SEMI fdb SEMI
00539
0170 00540 SEMI:
0170 DE 00 [4] 00541 ldx RS ; Pop IR from return stack
0172 08 [4] 00542 inx
0173 08 [4] 00543 inx
0174 DF 00 [5] 00544 stx RS
0176 EE 00 [6] 00545 ldx ,X
0178 DF 02 [5] 00546 stx IR
00547 ; mov SI,[BP] ; Pop return address
00548 ; add BP,2
00549
017A 00550 Next:
017A DE 02 [4] 00551 ldx IR
017C 08 [4] 00552 Next1 inx
017D 08 [4] 00553 inx
017E DF 02 [5] 00554 stx IR
0180 EE 00 [6] 00555 ldx ,X
00556 ; mov DI,[SI] ; Get next word address
00557 ; add SI,2
00558
0182 00559 RUN: ; WA in X
0182 DF 04 [5] 00560 stx WA ; Run machine code of new word
DEI Research 6800 Cross Assembler Version 0.0 05-16-2015 112:47:26 Page 11
tilli.a68
Addr Code Cycles Line# Source Statement
0184 EE 00 [6] 00561 Run1 ldx ,X
0186 6E 00 [4] 00562 jmp ,X
00563 ; mov BX,[DI] ; Run a threaded word
00564 ; add DI,2
00565 ; jmp BX
00566
0188 00567 __COLON:
0188 DE 00 [4] 00568 ldx RS ; Push instruction register
018A D6 03 [3] 00569 ldab IR+1 ; on return stack
018C 09 [4] 00570 dex
018D E7 02 [6] 00571 stab 2,X
018F 96 02 [3] 00572 ldaa IR
0191 09 [4] 00573 dex
0192 A7 02 [6] 00574 staa 2,X
0194 DF 00 [5] 00575 stx RS
00576
0196 DE 04 [4] 00577 ldx WA ; Execute new secondary
0198 20 E2 (017C) [4] 00578 bra Next1
00579 ; sub BP,2 ; Push instruction register
00580 ; mov [BP],SI
00581 ; mov SI,DI ; Point to nested secondary
00582 ; jmp short NEXT
And finally the AVR:
00572 ;=== < Inner interpreter >====================================================
00573
00574 ;-----------------------------------------------------------------------------
00575 ;
00576 ; SEMI does not have a header, but has a standard word address
00577 ;
00578 .init
0146 0102 00579 ?SEMI: .dw SEMI
00580 .cseg
00581
000102 01F7 [1] 00582 SEMI: movw R30,R14 ; Pop return address
000103 91A1 [2] 00583 ld R26,Z+
000104 91B1 [2] 00584 ld R27,Z+
000105 017F [1] 00585 movw R14,R30
00586 ; mov SI,[BP]
00587 ; add BP,2
00588
000106 91CD [2] 00589 Next: ld R28,X+ ; Get next word address in secondary
000107 91DD [2] 00590 ld R29,X+
00591 ; mov DI,[SI]
00592 ; add SI,2
00593
000108 91E9 [2] 00594 Run: ld R30,Y+ ; Run the word
000109 91F9 [2] 00595 ld R31,Y+
00010A 9409 [2] 00596 ijmp
00597 ; mov BX,[DI]
00598 ; add DI,2
00599 ; jmp BX
00600
00010B 00601 ?COLON:
00010B 01F7 [1] 00602 movw R30,R14 ; Push instruction register
00010C 93B2 [2] 00603 st -Z,R27
00010D 93A2 [2] 00604 st -Z,R26
00010E 017F [1] 00605 movw R14,R30
00010F 01DE [1] 00606 movw R26,R28 ; Point to nested secondary
000110 CFF5=000106 [2] 00607 rjmp Next ; And run it
00608 ; sub BP,2
00609 ; mov [BP],SI
00610 ; mov SI,DI
00611 ; jmp short Next
00612
00613 ;-----------------------------------------------------------------------------
00614 ;
00615 ; EXECUTE ( addr -- )
00616 ;
00617 ; Execute dictionary entry at compilation address on stack; for example,
00618 ; address returned by FIND.
00619 ;
00620 .init
00621 header "EXECUTE",0
+ =00000148 .set THIS_ENTRY = PC
+0148 0138 .dw PREV_ENTRY
+ =00000148 .set PREV_ENTRY = THIS_ENTRY
+014A 0745584543555445 .db 0 | strlen("EXECUTE"),"EXECUTE"
DEI Research AVR Cross Assembler Version 0.0 Jun-23-2015 57:32:32 Page 12
tilli.ASM
Addr Code Cycles Line# Source Statement
0152 0111 00622 _EXECUTE: .dw __EXECUTE
00623 .cseg
00624
000111 00625 __EXECUTE:
000111 91CF [2] 00626 pop R28 ; Get word address of the new word
000112 91DF [2] 00627 pop R29
000113 CFF4=000108 [2] 00628 rjmp Run
00629 ; pop DI
00630 ; jmp Run