CamelForth for the Motorola 6809 (c) 1995 Bradford J. Rodriguez * Permission is granted to freely copy, modify, and * * distribute this program for personal or educational use. * * Commercial inquiries should be directed to the author at * * 221 King St. E., #32, Hamilton, Ontario L8N 1B5 Canada * Direct-Threaded Forth model for Motorola 6809 16 bit cell, 8 bit char, 8 bit (byte) adrs unit X = Forth W temporary address register Y = IP Interpreter Pointer U = RSP Return Stack Pointer S = PSP Parameter Stack Pointer D = TOS top parameter stack item DP = UP User Pointer (high byte) v1.0 alpha test version, 28 Apr 95 \ 6809 Source Code: boot parameters (c) 28apr95 bjr HEX 0E000 FFFF DICTIONARY ROM ROM 7A00 EQU UP-INIT \ UP must be page aligned. Stacks, 7A EQU UP-INIT-HI \ TIB, etc. init'd relative to UP. 6000 EQU DP-INIT \ starting RAM adrs for dictionary \ SM2 memory map with 8K RAM: 6000-7BFF RAM, 7C00-7FFF I/O \ Harvard synonyms - these must all be PRESUMEd AKA , I, AKA @ I@ AKA ! I! AKA C, IC, AKA C@ IC@ AKA C! IC! AKA HERE IHERE AKA ALLOT IALLOT PRESUME WORD AKA WORD IWORD \ 6809 DTC: SCC initialization (c) 17apr95 bjr HERE EQU SCCATBL HEX 7C02 , 2500 , \ port address, #bytes, reset reg ptr 09C0 , 0444 , 0100 , 0200 , 03C0 , 0560 , 0901 , 0A00 , 0B50 , 0C18 , 0D00 , 0E02 , 0E03 , 03C1 , 0568 , 0F00 , 1010 , 0100 , HERE EQU SCCBTBL 7C00 , 1F00 , \ port address, #bytes, reset reg ptr 0444 , 0100 , 03C0 , 0560 , 0A00 , 0B50 , 0C18 , 0D00 , 0E02 , 0E03 , 03C1 , 0568 , 0F00 , 1010 , 0100 , \ 0909 , ASM: HERE EQU SCCINIT \ set up on-board i/o X ,++ LDY, X ,+ LDB, BEGIN, X ,+ LDA, Y 0, STA, DECB, EQ UNTIL, RTS, ;C \ 6809 DTC: serial I/O (c) 31mar95 bjr HEX 7C02 EQU SCCACMD 7C03 EQU SCCADTA CODE KEY \ -- c get char from serial port 6 # ( D) PSHS, BEGIN, SCCACMD LDB, 1 # ANDB, NE UNTIL, SCCADTA LDB, CLRA, NEXT ;C CODE KEY? \ -- f return true if char waiting 6 # ( D) PSHS, CLRA, SCCACMD LDB, 1 # ANDB, NE IF, -1 # LDB, THEN, NEXT ;C CODE EMIT \ c -- output character to serial port BEGIN, SCCACMD LDA, 4 # ANDA, NE UNTIL, SCCADTA STB, 6 # ( D) PULS, NEXT ;C \ 6809 DTC: interpreter logic (c) 17apr95 bjr ASM: HERE RESOLVES DOCOLON HERE EQU HEX 20 # ( Y) PSHU, 20 # PULS, NEXT, ;C ASM: HERE RESOLVES DOCREATE HERE EQU 10 # ( X) PULS, 6 # ( D) PSHS, X D TFR, NEXT, ;C CODE EXIT \ -- exit a colon definition HEX 20 # ( Y) PULU, NEXT ;C CODE LIT \ -- x fetch inline literal to stack 6 # ( D) PSHS, Y ,++ LDD, NEXT ;C CODE EXECUTE \ i*x xt -- j*x execute Forth word at 'xt' D X TFR, 6 # ( D) PULS, X 0, JMP, ;C \ 6809 DTC: stack operations (c) 31mar95 bjr CODE DUP \ x -- x x duplicate top of stack 6 # ( D) PSHS, NEXT ;C CODE ?DUP \ x -- 0 | x x DUP if nonzero 0 # CMPD, NE IF, 6 # ( D) PSHS, THEN, NEXT ;C CODE DROP \ x -- drop top of stack 6 # ( D) PULS, NEXT ;C CODE SWAP \ x1 x2 -- x2 x1 swap top two items S 0, LDX, S 0, STD, X D TFR, NEXT ;C CODE OVER \ x1 x2 -- x1 x2 x1 per stack diagram 6 # ( D) PSHS, S 2 , LDD, NEXT ;C \ 6809 DTC: stack operations (c) 31mar95 bjr CODE ROT \ x1 x2 x3 -- x2 x3 x1 per stack diagram S 0, LDX, S 0, STD, S 2 , LDD, S 2 , STX, NEXT ;C CODE NIP \ x1 x2 -- x2 per stack diagram S 2 , LEAS, NEXT ;C CODE TUCK \ x1 x2 -- x2 x1 x2 per stack diagram S 0, LDX, S 0, STD, HEX 10 # ( X) PSHS, NEXT ;C CODE >R \ x -- R: -- x push to return stack 6 # ( D) PSHU, 6 # ( D) PULS, NEXT ;C CODE R> \ -- x R: x -- pop from return stack 6 # ( D) PSHS, 6 # ( D) PULU, NEXT ;C \ 6809 DTC: stack operations (c) 31mar95 bjr CODE R@ \ -- x R: x -- x fetch from return stack 6 # ( D) PSHS, U 0, LDD, NEXT ;C CODE SP@ \ -- a-addr get data stack pointer 6 # ( D) PSHS, S D TFR, NEXT ;C CODE SP! \ a-addr -- set data stack pointer D S TFR, 6 # ( D) PULS, NEXT ;C CODE RP@ \ -- a-addr get return stack pointer 6 # ( D) PSHS, U D TFR, NEXT ;C CODE RP! \ a-addr -- set return stack pointer D U TFR, 6 # ( D) PULS, NEXT ;C \ 6809 DTC: memory operations (c) 31mar95 bjr CODE ! \ x a-addr -- store cell in memory D X TFR, 6 # ( D) PULS, X 0, STD, 6 # ( D) PULS, NEXT ;C CODE C! \ char c-addr -- store char in memory D X TFR, 6 # ( D) PULS, X 0, STB, 6 # ( D) PULS, NEXT ;C CODE @ \ a-addr -- x fetch cell from memory D X TFR, X 0, LDD, NEXT ;C CODE C@ \ c-addr -- char fetch char from memory D X TFR, X 0, LDB, CLRA, NEXT ;C \ 6809 DTC: arithmetic operations (c) 26apr95 bjr CODE + \ n1/u1 n2/u2 -- n3/u3 add n1+n2 S ,++ ADDD, NEXT ;C CODE M+ \ d n -- d add single to double S 2 , ADDD, S 2 , STD, 6 # ( D) PULS, 0 # ADCB, 0 # ADCA, NEXT ;C CODE - \ n1/u1 n2/u2 -- n3/u3 subtract n1-n2 S ,++ SUBD, COMA, COMB, 1 # ADDD, NEXT ;C CODE NEGATE \ x1 -- x2 two's complement COMA, COMB, 1 # ADDD, NEXT ;C \ 6809 DTC: logical operations (c) 31mar95 bjr CODE AND \ x1 x2 -- x3 logical AND S ,+ ANDA, S ,+ ANDB, NEXT ;C CODE OR \ x1 x2 -- x3 logical OR S ,+ ORA, S ,+ ORB, NEXT ;C CODE XOR \ x1 x2 -- c3 logical XOR S ,+ EORA, S ,+ EORB, NEXT ;C CODE INVERT \ x1 -- x2 bitwise inversion COMA, COMB, NEXT ;C CODE >< \ x1 -- x2 swap bytes A B EXG, NEXT ;C \ 6809 DTC: arithmetic operations (c) 31mar95 bjr CODE 1+ \ n1/u1 -- n2/u2 add 1 to TOS 1 # ADDD, NEXT ;C CODE 1- \ n1/u1 -- n2/u2 subtract 1 from TOS 1 # SUBD, NEXT ;C CODE 2* \ x1 -- x2 arithmetic left shift ASLB, ROLA, NEXT ;C CODE 2/ \ x1 -- x2 arithmetic right shift ASRA, RORB, NEXT ;C CODE +! \ n/u a-addr -- add cell to memory D X TFR, 6 # ( D) PULS, X 0, ADDD, X 0, STD, 6 # ( D) PULS, NEXT ;C \ 6809 DTC: arithmetic operations (c) 31mar95 bjr CODE LSHIFT \ x1 u -- x2 logical shift left u places D X TFR, 6 # ( D) PULS, X 0, LEAX, NE IF, BEGIN, LSLB, ROLA, X -1 , LEAX, EQ UNTIL, THEN, NEXT ;C CODE RSHIFT \ x1 u -- x2 logical shift right u places D X TFR, 6 # ( D) PULS, X 0, LEAX, NE IF, BEGIN, LSRA, RORB, X -1 , LEAX, EQ UNTIL, THEN, NEXT ;C \ 6809 DTC: comparison operations (c) 31mar95 bjr CODE 0= \ n/u -- flag return true if TOS=0 0 # CMPD, EQ IF, HERE EQU TOSTRUE -1 # LDD, NEXT THEN, CLRA, CLRB, NEXT ;C CODE 0< \ n/u -- flag true if TOS negative TSTA, TOSTRUE BMI, CLRA, CLRB, NEXT ;C CODE = \ x1 x2 -- flag test x1=x2 S ,++ SUBD, TOSTRUE BEQ, CLRA, CLRB, NEXT ;C CODE <> \ x1 x2 -- flag test not equal S ,++ SUBD, TOSTRUE BNE, CLRA, CLRB, NEXT ;C \ 6809 DTC: comparison operations (c) 31mar95 bjr CODE < \ n1 n2 -- flag test n1 \ n1 n2 -- flag test n1>n2, signed S ,++ SUBD, TOSTRUE BLT, CLRA, CLRB, NEXT ;C CODE U< \ n1 n2 -- flag test n1 \ n1 n2 -- flag test n1>n2, unsigned S ,++ SUBD, TOSTRUE BLO, CLRA, CLRB, NEXT ;C \ 6809 DTC: branch and loop operations (c) 31mar95 bjr CODE BRANCH \ -- branch always Y 0, LDY, NEXT ;C CODE ?BRANCH \ x -- branch if TOS zero 0 # CMPD, EQ IF, 6 # ( D) PULS, Y 0, LDY, NEXT THEN, 6 # ( D) PULS, Y 2 , LEAY, NEXT ;C CODE (DO) \ n1|u1 n2|u2 -- R: -- sys1 sys2 D X TFR, HEX 8000 # LDD, S ,++ SUBD, \ fudg=8000-limit 6 # ( D) PSHU, X D, LEAX, 10 # ( X) PSHU, \ start+fudg 6 # ( D) PULS, NEXT ;C CODE UNLOOP \ -- R: sys1 sys2 -- drop loop parameters U 4 , LEAU, NEXT ;C \ 6809 DTC: branch and loop operations (c) 31mar95 bjr CODE (LOOP) \ R: sys1 sys2 -- | sys1 sys2 run-time for LOOP 6 # ( D) PSHS, U 0, LDD, 1 # ADDD, VC IF, HERE EQU TAKELOOP U 0, STD, Y 0, LDY, 6 # PULS, NEXT THEN, Y 2 , LEAY, U 4 , LEAU, 6 # PULS, NEXT ;C CODE (+LOOP) \ n -- R: sys1 sys2 -- | sys1 sys2 for +LOOP U 0, ADDD, TAKELOOP BVC, Y 2 , LEAY, U 4 , LEAU, 6 # PULS, NEXT ;C CODE I \ -- n R: sys1 sys2 -- sys1 sys2 loop index 6 # ( D) PSHS, U 0, LDD, U 2 , SUBD, NEXT ;C CODE J \ -- n R: 4*sys -- 4*sys 2nd loop index 6 # ( D) PSHS, U 4 , LDD, U 6 , SUBD, NEXT ;C \ 6809 DTC: multiply (c) 25apr95 bjr CODE UM* \ u1 u2 -- ud 16*16->32 unsigned multiply 16 # ( X,D) PSHS, \ push temporary, u2 S 5 , LDA, S 1 , LDB, MUL, S 2 , STD, \ 1lo*2lo S 4 , LDA, S 1 , LDB, MUL, \ 1hi*2lo S 2 , ADDB, 0 # ADCA, S 1 , STD, S 5 , LDA, S 0, LDB, MUL, \ 1lo*2hi S 1 , ADDD, S 1 , STD, CLRA, ROLA, \ cy in A S 0, LDB, S 0, STA, S 4 , LDA, MUL, \ 2hi*1hi S 0, ADDD, \ hi result in D S 2 , LDX, S 4 , LEAS, S 0, STX, NEXT ;C \ lo result \ 6809 DTC: divide (c) 25apr95 bjr CODE UM/MOD \ ud u1 -- rem quot 32/16->16 divide HEX 6 # PSHS, 10 # LDX, \ save u1 in mem S 5 , ASL, S 4 , ROL, \ initial shift (lo 16) BEGIN, S 3 , ROL, S 2 , ROL, S 2 , LDD, \ shift left hi 16 CS IF, \ 1xxxx: 17 bits, subtract is ok S 0, SUBD, S 2 , STD, 0FE # ANDCC, \ clear cy ELSE, \ 0xxxx: 16 bits, test subtract S 0, SUBD, CC IF, S 2 , STD, THEN, \ cs=can't subtr THEN, \ cy=0 if sub ok, 1 if no subtract S 5 , ROL, S 4 , ROL, \ rotate cy into result X -1 , LEAX, EQ UNTIL, \ loop 16 times S 4 , LDD, COMA, COMB, \ invert to get true quot in D S 2 , LDX, S 4 , STX, S 4 , LEAS, \ save rem, clean stack NEXT ;C \ 6809 DTC: block and string operations (c) 31mar95 bjr CODE FILL \ c-addr u char -- fill mem with char HEX 20 # ( Y) PSHU, 30 # ( X,Y) PULS, \ D=char X=u Y=adr 0 # CMPX, NE IF, BEGIN, Y ,+ STB, X -1 , LEAX, EQ UNTIL, THEN, 6 # ( D) PULS, 20 # ( Y) PULU, NEXT, ;C CODE S= \ c-addr1 c-addr2 u -- n string compare 1:2 S 2 , ADDD, S 2 , LDX, S 2 , STY, \ X=src D=end S 0, LDY, S 0, STD, CLRB, \ Y=dst B=0 BEGIN, S 0, CMPX, NE WHILE, X ,+ LDA, Y ,+ SUBA, NE IF, 0 # SBCB, B A TFR, 1 # ORB, HEX 30 # ( X,Y) PULS, NEXT, THEN, REPEAT, B A TFR, HEX 30 # ( X,Y) PULS, NEXT, ;C \ 6809 DTC: block and string operations (c) 31mar95 bjr CODE CMOVE \ c-addr1 c-addr2 u -- move from bottom 1->2 S 2 , ADDD, S 2 , LDX, S 2 , STY, \ X=src D=end S 0, LDY, S 0, STD, \ Y=dst BEGIN, S 0, CMPX, NE WHILE, X ,+ LDB, Y ,+ STB, REPEAT, HEX 30 # ( X,Y) PULS, 6 # ( D) PULS, NEXT ;C CODE CMOVE> \ c-addr1 c-addr2 u -- move from top 1->2 S 2 , LDX, X D, LEAX, S 2 , STY, \ X=src D=u S 0, LDY, Y D, LEAY, \ Y=dst BEGIN, S 0, CMPY, NE WHILE, X -, LDB, Y -, STB, REPEAT, HEX 30 # ( X,Y) PULS, 6 # ( D) PULS, NEXT ;C \ 6809 DTC: block and string operations (c) 31mar95 bjr ASM: HERE EQU SKIPEXIT Y -1 , LEAY, HERE EQU SKIPDONE HEX 20 # PSHS, X D TFR, 20 # PULU, NEXT ;C CODE SKIP \ c-addr u c -- c-addr' u' skip matching chars HEX 20 # ( Y) PSHU, 30 # ( X,Y) PULS, \ D=char X=u Y=adr 0 # CMPX, NE IF, BEGIN, Y ,+ CMPB, SKIPEXIT BNE, X -1 , LEAX, EQ UNTIL, THEN, SKIPDONE BRA, ;C CODE SCAN \ c-addr u c -- c-addr' u' find matching char HEX 20 # ( Y) PSHU, 30 # ( X,Y) PULS, \ D=char X=u Y=adr 0 # CMPX, NE IF, BEGIN, Y ,+ CMPB, SKIPEXIT BEQ, X -1 , LEAX, EQ UNTIL, THEN, SKIPDONE BRA, ;C \ 6809 DTC: system dependencies (c) 21apr95 bjr \ These words are shorter in CODE than as colon definitions! CODE ALIGNED NEXT ;C \ a1 -- a2 align address CODE ALIGN NEXT ;C \ -- align HERE CODE CELL+ 2 # ADDD, NEXT ;C \ a1 -- a2 add cell size CODE CELLS ASLB, ROLA, NEXT ;C \ n1 -- n2 cells->adr units CODE CHAR+ 1 # ADDD, NEXT ;C \ a1 -- a2 add char size CODE CHARS NEXT ;C \ n1 -- n2 chars->adr units CODE >BODY 3 # ADDD, NEXT ;C \ xt -- a-addr cfa->pfa AKA 1- CHAR- \ Note: CELL, a constant, must be defined after CONSTANT. \ 6809 DTC: system dependencies (c) 21apr95 bjr HEX : COMPILE, , ; \ xt -- append execution tokn : !CF 0BD OVER C! 1+ ! ; \ adrs cfa -- set code field : ,CF HERE !CF 3 ALLOT ; \ adrs -- append code field : !COLON -3 ALLOT ,CF ; \ -- changes last c.f. : ,EXIT ['] EXIT COMPILE, ; \ -- append EXIT action : ,BRANCH , ; \ xt -- append branch instr. : ,DEST , ; \ dest -- append dest'n adrs : !DEST ! ; \ dest adr -- change dest'n \ 6809 DTC: dodoes (does>) does> (c) 18apr95 bjr ASM: HERE RESOLVES DODOES HERE EQU HEX 20 # ( Y) PSHU, 20 # ( Y) PULS, \ adrs of DODOES code 10 # ( X) PULS, 6 # ( D) PSHS, X D TFR, \ adrs of data NEXT, ;C DECIMAL \ to keep ,CF from compiling as a hex number : (DOES>) R> LATEST @ NFA>CFA !CF ; : DOES> ['] (DOES>) COMPILE, ,CF ; IMMEDIATE \ 6809 DTC: defining words (c) 21apr95 bjr : : CREATE HIDE ] !COLON ; : ; REVEAL ,EXIT [COMPILE] [ ; IMMEDIATE : CONSTANT CREATE , ;CODE HEX 10 # ( X) PULS, 6 # ( D) PSHS, X 0, LDD, NEXT, ;C EMULATE: TCREATE T, MDOES> T@ ;EMULATE : VARIABLE CREATE CELL ALLOT ; EMULATE: TCREATE 0 T, MDOES> ;EMULATE : USER CREATE , ;CODE HEX 10 # ( X) PULS, 6 # ( D) PSHS, \ get pfa in X DPR A TFR, CLRB, X 0, ADDD, NEXT, ;C \ UP+offset -> D EMULATE: TCREATE T, MDOES> .UNDEF ;EMULATE \ High level: control structures (c) 21apr95 bjr : IF \ -- adrs conditional forward branch ['] ?BRANCH ,BRANCH HERE DUP ,DEST ; EMULATE: M['] ?BRANCH T, THERE DUP T, ;EMULATE IMMEDIATE : THEN \ adrs -- resolve forward branch HERE SWAP !DEST ; EMULATE: THERE SWAP T! ;EMULATE IMMEDIATE : ELSE \ adrs1 -- adrs2 branch for IF..ELSE ['] BRANCH ,BRANCH HERE DUP ,DEST SWAP [COMPILE] THEN ; EMULATE: M['] BRANCH T, THERE DUP T, SWAP THERE SWAP T! ;EMULATE IMMEDIATE \ High level: control structures (c) 21apr95 bjr : BEGIN HERE ; \ -- adrs target for backward branch EMULATE: THERE ;EMULATE IMMEDIATE : UNTIL \ adrs -- conditional backward branch ['] ?BRANCH ,BRANCH ,DEST ; EMULATE: M['] ?BRANCH T, T, ;EMULATE IMMEDIATE : AGAIN \ adrs -- unconditional backward branch ['] BRANCH ,BRANCH ,DEST ; EMULATE: M['] BRANCH T, T, ;EMULATE IMMEDIATE : WHILE \ -- adrs branch for WHILE loop [COMPILE] IF ; EMULATE: M['] ?BRANCH T, THERE DUP T, ;EMULATE IMMEDIATE \ High level: control structures (c) 21apr95 bjr : REPEAT \ adrs1 adrs2 --- resolve WHILE loop SWAP [COMPILE] AGAIN [COMPILE] THEN ; EMULATE: SWAP M['] BRANCH T, T, THERE SWAP T! ;EMULATE IMMEDIATE : >L CELL LP +! LP @ ! ; : L> LP @ @ CELL NEGATE LP +! ; : DO \ -- adrs L: -- 0 ['] (DO) ,BRANCH HERE 0 >L ; EMULATE: M['] (DO) T, THERE 0 T>L ;EMULATE IMMEDIATE : LEAVE ['] UNLOOP COMPILE, ['] BRANCH ,BRANCH HERE DUP ,DEST >L ; EMULATE: M['] UNLOOP T, M['] BRANCH T, THERE DUP T, T>L ;EMULATE IMMEDIATE \ High level: control structures (c) 21apr95 bjr : ENDLOOP ,BRANCH ,DEST \ adrs xt -- L: 0 a1 a2 .. aN -- BEGIN L> ?DUP WHILE [COMPILE] THEN REPEAT ; ALSO FORTH ALSO META DEFINITIONS : TENDLOOP T, T, BEGIN TL> ?DUP WHILE THERE SWAP T! REPEAT ; PREVIOUS PREVIOUS DEFINITIONS : LOOP ['] (LOOP) ENDLOOP ; EMULATE: M['] (LOOP) TENDLOOP ;EMULATE IMMEDIATE : +LOOP ['] (+LOOP) ENDLOOP ; EMULATE: M['] (+LOOP) TENDLOOP ;EMULATE IMMEDIATE \ High level: system variables and constants (c) 21apr95 bjr HEX 2 CONSTANT CELL \ system dependent constant 20 CONSTANT BL 7E CONSTANT TIBSIZE \ High level: system variables and constants (c) 31mar95 bjr HEX -80 USER TIB \ -- a-addr Terminal Input Buffer 0 USER U0 \ -- a-addr current user area adrs 2 USER >IN \ -- a-addr holds offset into TIB 4 USER BASE \ -- a-addr holds conversion radix 6 USER STATE \ -- a-addr holds compiler state 8 USER DP \ -- a-addr holds dictionary pointer 0A USER 'SOURCE \ -- a-addr two cells: length, address 0E USER LATEST \ -- a-addr last word in dictionary 10 USER HP \ -- a-addr HOLD pointer 12 USER LP \ -- a-addr leave-stack pointer 100 USER S0 \ -- a-addr end of parameter stack 128 USER PAD \ -- a-addr user PAD buffer/end of hold 180 USER L0 \ -- a-addr bottom of leave stack 200 USER R0 \ -- a-addr end of return stack \ High level: arithmetic operators (c) 31mar95 bjr : S>D \ n -- d single -> double precision DUP 0< ; : ?NEGATE \ n1 n2 -- n3 negate n1 if n2 negative 0< IF NEGATE THEN ; : ABS \ n1 -- n2 absolute value DUP ?NEGATE ; : DNEGATE \ d1 -- d2 negate, double precision SWAP INVERT SWAP INVERT 1 M+ ; : ?DNEGATE \ d1 n -- d2 negate d1 if n negative 0< IF DNEGATE THEN ; : DABS \ d1 -- d2 absolute value, double precision DUP ?DNEGATE ; \ High level: arithmetic operators (c) 31mar95 bjr : M* \ n1 n2 -- d signed 16*16->32 multiply 2DUP XOR >R SWAP ABS SWAP ABS UM* R> ?DNEGATE ; : SM/REM \ d1 n1 -- n2 n3 symmetric signed division 2DUP XOR >R OVER >R ABS >R DABS R> UM/MOD SWAP R> ?NEGATE SWAP R> ?NEGATE ; \ High level: arithmetic operators (c) 31mar95 bjr : FM/MOD \ d1 n1 -- n2 n3 floored signed division DUP >R SM/REM DUP 0< IF SWAP R> + SWAP 1- ELSE R> DROP THEN ; : * \ n1 n2 -- n3 signed multiply M* DROP ; : /MOD \ n1 n2 -- n3 n4 signed divide/remainder >R S>D R> FM/MOD ; : / \ n1 n2 -- n3 signed divide /MOD NIP ; \ High level: arithmetic operators (c) 31mar95 bjr : MOD \ n1 n2 -- n3 signed remainder /MOD DROP ; : */MOD \ n1 n2 n3 -- n4 n5 n1*n2/n3, remainder"ient >R M* R> FM/MOD ; : */ \ n1 n2 n3 -- n4 n1*n2/n3 */MOD NIP ; : MAX \ n1 n2 -- n3 signed maximum 2DUP < IF SWAP THEN DROP ; : MIN \ n1 n2 -- n3 signed minimum 2DUP > IF SWAP THEN DROP ; \ High level: double operators (c) 31mar95 bjr : 2@ \ a-addr -- x1 x2 fetch 2 cells DUP CELL+ @ SWAP @ ; : 2! \ x1 x2 a-addr -- store 2 cells SWAP OVER ! CELL+ ! ; : 2DROP \ x1 x2 -- drop 2 cells DROP DROP ; : 2DUP \ x1 x2 -- x1 x2 x1 x2 dup top 2 cells OVER OVER ; : 2SWAP \ x1 x2 x3 x4 -- x3 x4 x1 x2 per diagram ROT >R ROT R> ; : 2OVER \ x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2 per diagram >R >R 2DUP R> R> 2SWAP ; \ High level: input/output (c) 31mar95 bjr HEX : COUNT \ c-addr1 -- c-addr2 u counted->addr/length DUP CHAR+ SWAP C@ ; : CR \ -- output newline 0D EMIT 0A EMIT ; : SPACE \ -- output a space BL EMIT ; : SPACES \ u -- output u spaces BEGIN DUP WHILE SPACE 1- REPEAT DROP ; : UMIN \ u1 u2 -- u unsigned minimum 2DUP U> IF SWAP THEN DROP ; : UMAX \ u1 u2 -- u unsigned maximum 2DUP U< IF SWAP THEN DROP ; \ High level: input/output (c) 31mar95 bjr : ACCEPT \ c-addr +n -- +n' get line from terminal OVER + 1- OVER BEGIN KEY DUP 0D <> WHILE DUP EMIT DUP 8 = IF DROP 1- >R OVER R> UMAX ELSE OVER C! 1+ OVER UMIN THEN REPEAT DROP NIP SWAP - ; : TYPE \ c-addr +n -- type line to terminal ?DUP IF OVER + SWAP DO I C@ EMIT LOOP ELSE DROP THEN ; \ High level: input/output (c) 31mar95 bjr : (S") \ -- c-addr u run-time code for S" R> COUNT 2DUP + ALIGN >R ; ALSO FORTH ALSO META DEFINITIONS : TS" 22 WORD DUP C@ 1+ THERE OVER TALLOT SWAP >TCMOVE ; PREVIOUS PREVIOUS DEFINITIONS : S" \ -- compile in-line string ['] (S") COMPILE, 22 WORD C@ 1+ ALIGNED ALLOT ; EMULATE: M['] (S") T, TS" ;EMULATE IMMEDIATE : ." \ -- compile string to print [COMPILE] S" ['] TYPE COMPILE, ; EMULATE: M['] (S") T, TS" M['] TYPE T, ;EMULATE IMMEDIATE \ High level: numeric output (c) 31mar95 bjr : UD/MOD \ ud1 u2 -- u3 ud4 32/16->32 divide >R 0 R@ UM/MOD ROT ROT R> UM/MOD ROT ; : UD* \ ud1 u2 -- ud3 32*16->32 multiply DUP >R UM* DROP SWAP R> UM* ROT + ; : HOLD \ char -- add char to output string -1 HP +! HP @ C! ; : <# \ -- begin numeric conversion PAD HP ! ; : >DIGIT \ n -- c convert to 0..9A..Z DUP 9 > 7 AND + 30 + ; : # \ ud1 -- ud2 convert 1 digit of output BASE @ UD/MOD ROT >DIGIT HOLD ; : #S \ ud1 -- ud2 convert remaining digits BEGIN # 2DUP OR 0= UNTIL ; \ High level: numeric output (c) 31mar95 bjr : #> \ ud1 -- c-addr u end conversion, get string 2DROP HP @ PAD OVER - ; : SIGN \ n -- add minus sign if n<0 0< IF 2D HOLD THEN ; : U. \ u -- display u unsigned <# 0 #S #> TYPE SPACE ; : . \ n -- display n signed <# DUP ABS 0 #S ROT SIGN #> TYPE SPACE ; : DECIMAL \ -- set number base to decimal 0A BASE ! ; : HEX \ -- set number base to hex 10 BASE ! ; \ High level: dictionary management (c) 31mar95 bjr : HERE \ -- addr returns dictionary ptr DP @ ; : ALLOT \ n -- allocate n adr units in dict DP +! ; : , \ x -- append cell to dict HERE ! 1 CELLS ALLOT ; : C, \ char -- append char to dict HERE C! 1 CHARS ALLOT ; \ High level: interpreter (c) 31mar95 bjr : SOURCE \ -- adr n current input buffer 'SOURCE 2@ ; : /STRING \ a u n -- a+n u-n trim string ROT OVER + ROT ROT - ; : >COUNTED \ src n dst -- copy to counted string 2DUP C! CHAR+ SWAP CMOVE ; : WORD \ char -- c-addr word delim'd by char DUP SOURCE >IN @ /STRING DUP >R ROT SKIP OVER >R ROT SCAN DUP IF CHAR- THEN R> R> ROT - >IN +! TUCK - HERE >COUNTED HERE BL OVER COUNT + C! ; \ High level: interpreter (c) 31mar95 bjr : NFA>LFA \ nfa -- lfa name adr -> link field 3 - ; : NFA>CFA \ nfa -- cfa name adr -> code field COUNT 7F AND + ; : IMMED? \ nfa -- f fetch immediate flag 1- C@ ; : FIND \ c-addr -- c-addr 0/1/-1 not found/immed/normal LATEST @ BEGIN \ -- a nfa 2DUP OVER C@ CHAR+ \ -- a nfa a nfa n+1 S= DUP IF DROP NFA>LFA @ DUP THEN \ -- a link link 0= UNTIL \ -- a nfa OR a 0 DUP IF \ if found, check immed status NIP DUP NFA>CFA \ -- nfa xt SWAP IMMED? 0= 1 OR \ -- xt 1/-1 THEN ; \ High level: interpreter (c) 31mar95 bjr : LITERAL \ x -- append numeric literal STATE @ IF ['] LIT COMPILE, I, THEN ; EMULATES TLITERAL IMMEDIATE HEX : DIGIT? \ c -- n -1 | x 0 true if c is a valid digit DUP 39 > 100 AND + \ silly looking, DUP 140 > 107 AND - 30 - \ but it works! DUP BASE @ U< ; : ?SIGN \ adr n -- adr' n' f get optional sign OVER C@ \ -- adr n c 2C - DUP ABS 1 = AND \ -- +=-1, -=+1, else 0 DUP IF 1+ \ +=0, -=+2 NZ=negative >R 1 /STRING R> \ adr' n' f THEN ; \ High level: interpreter (c) 31mar95 bjr : >NUMBER \ ud adr u -- ud' adr' u' conv. string to number BEGIN DUP WHILE OVER C@ DIGIT? 0= IF DROP EXIT THEN >R 2SWAP BASE @ UD* R> M+ 2SWAP 1 /STRING REPEAT ; : ?NUMBER \ c-addr -- n -1 | c-addr 0 string->number DUP 0 0 ROT COUNT \ -- ca ud adr n ?SIGN >R >NUMBER \ -- ca ud adr' n' IF R> 2DROP 2DROP 0 \ -- ca 0 (error) ELSE 2DROP NIP R> IF NEGATE THEN -1 \ -- n -1 (ok) THEN ; \ High level: interpreter (c) 31mar95 bjr : INTERPRET \ i*x c-addr u -- j*x interpret given buffer 'SOURCE 2! 0 >IN ! BEGIN BL WORD DUP C@ WHILE \ -- textadr FIND ?DUP IF \ -- xt 1/-1 1+ STATE @ 0= OR \ immed or interp? IF EXECUTE ELSE COMPILE, THEN ELSE \ -- textadr ?NUMBER IF [COMPILE] LITERAL \ converted ok ELSE COUNT TYPE 3F EMIT CR ABORT THEN \ error THEN REPEAT DROP ; : EVALUATE \ i*x c-addr u -- j*x interpret string 'SOURCE 2@ >R >R >IN @ >R INTERPRET R> >IN ! R> R> 'SOURCE 2! ; \ High level: interpreter (c) 28apr95 bjr : QUIT \ -- R: i*x -- interpret from keyboard L0 LP ! R0 RP! 0 STATE ! \ reset stacks, state BEGIN TIB DUP TIBSIZE ACCEPT SPACE INTERPRET STATE @ 0= IF CR ." OK " THEN AGAIN ; : ABORT \ i*x -- R: j*x -- clear stack and QUIT S0 SP! QUIT ; : ?ABORT \ f c-addr u -- abort and print message ROT IF TYPE ABORT THEN 2DROP ; : ABORT" \ i*x 0 -- i*x abort, print inline msg [COMPILE] S" ['] ?ABORT COMPILE, ; EMULATE: M['] (S") T, TS" M['] ?ABORT T, ;EMULATE IMMEDIATE \ High level: interpreter (c) 31mar95 bjr : ' \ -- xt find word in dictionary BL WORD FIND 0= ABORT" ?" ; : CHAR \ -- char parse ASCII character BL WORD 1+ C@ ; : [CHAR] \ -- compile character literal CHAR ['] LIT COMPILE, I, ; IMMEDIATE : ( \ -- skip input until ) 29 WORD DROP ; IMMEDIATE \ High level: compiler (c) 31mar95 bjr : CREATE \ -- create an empty definition LATEST @ I, 0 IC, \ link & immediate field IHERE LATEST ! \ new "latest" link BL IWORD IC@ 1+ IALLOT \ name field ,CF ; \ code field : RECURSE \ -- recurse current definition LATEST @ NFA>CFA COMPILE, ; IMMEDIATE : [ \ -- enter interpretive state 0 STATE ! ; IMMEDIATE : ] \ -- enter compiling state -1 STATE ! ; \ High level: compiler (c) 31mar95 bjr HEX : HIDE \ -- "hide" latest definition LATEST @ DUP IC@ 80 OR SWAP IC! ; : REVEAL \ -- "reveal" latest definition LATEST @ DUP IC@ 7F AND SWAP IC! ; : IMMEDIATE \ -- make last definition immediate 1 LATEST @ 1- IC! ; : ['] \ -- find word and compile as literal ' ['] LIT COMPILE, I, ; IMMEDIATE \ High level: compiler (c) 31mar95 bjr : POSTPONE \ -- postpone compile action of word BL WORD FIND DUP 0= ABORT" ?" \ find word 0< IF ['] LIT COMPILE, I, \ non-immed: compiles later ['] COMPILE, COMPILE, \ add "LIT xt COMPILE," to df ELSE COMPILE, THEN ; IMMEDIATE \ immed: compile into df \ High level: other operations (c) 25apr95 bjr : WITHIN \ n1|u1 n2|u2 n3|u3 -- f n2<=n1R - R> U< ; : MOVE \ addr1 addr2 u -- smart move >R 2DUP SWAP DUP R@ + WITHIN IF R> CMOVE> ELSE R> CMOVE THEN ; : DEPTH \ -- n SP@ S0 SWAP - 2/ ; \ 16 BIT VERSION! : ENVIRONMENT? \ c-addr u -- i*x true system query 2DROP 0 ; \ -- false \ High level: utility words (c) 25apr95 bjr : WORDS \ -- list all words in dictionary LATEST @ BEGIN DUP COUNT TYPE SPACE NFA>LFA @ DUP 0= UNTIL DROP ; EMULATES WORDS : .S \ -- print contents of stack SP@ S0 - IF SP@ S0 2 - DO I @ h. -2 +LOOP THEN ; EMULATES .S \ High level: startup (c) 25apr95 bjr : COLD \ -- cold start Forth system UINIT U0 #INIT CMOVE ." 6809 CamelForth v1.0 25 Apr 95" CR ABORT ; \ Testing words HEX : .H ( n - ) 0F AND 30 + DUP 39 > IF 7 + THEN EMIT ; : .HH ( n - ) DUP 2/ 2/ 2/ 2/ .H .H ; : .HHHH ( n - ) DUP 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ .HH .HH ; : H. ( n - ) .HHHH SPACE ; : .B ( a - a+1 ) DUP C@ .HH SPACE 1+ ; : DUMP ( a n - ) 0 DO DUP CR H. SPACE .B .B .B .B .B .B .B .B SPACE .B .B .B .B .B .B .B .B 10 +LOOP DROP ; \ 6809 DTC: reset initialization (c) 25apr95 bjr ASM: HERE EQU ENTRY HEX CLRA, F000 STA, INCA, E000 STA, INCA, D000 STA, INCA, C000 STA, INCA, B000 STA, INCA, A000 STA, INCA, 9000 STA, INCA, 8000 STA, \ init mem mapping UP-INIT-HI # LDA, A DPR TFR, \ initial UP UP-INIT 100 + # LDS, \ initial SP UP-INIT 200 + # LDU, \ initial RP SCCATBL # LDX, SCCINIT JSR, \ init serial ports SCCBTBL # LDX, SCCINIT JSR, ' COLD JMP, ;C \ enter top-level Forth word ASM: HERE EQU IRET RTI, ;C HERE 0FFF0 ORG \ 6809 hardware vectors IRET , IRET , IRET , IRET , \ tbd, SWI3, SWI2, FIRQ IRET , IRET , IRET , ENTRY , \ IRQ, SWI, NMI, RESET ORG \ 6809 DTC: user area initialization (c) 25apr95 bjr DECIMAL 18 CONSTANT #INIT \ # bytes of user area init data CREATE UINIT HEX 0 , 0 , 0A , 0 , \ reserved,>IN,BASE,STATE DP-INIT , \ DP 0 , 0 , \ SOURCE init'd elsewhere META ALSO FORTH TLATEST @ T, PREVIOUS TARGET \ LATEST 0 , \ HP init'd elsewhere \ Note that UINIT must be the *last* word in the kernel, in \ order to set the initial LATEST as shown above. If this is \ not the last word, be sure to patch the LATEST value above.