Camel09
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 <DOCOLON>
HEX 20 # ( Y) PSHU, 20 # PULS, NEXT, ;C
ASM: HERE RESOLVES DOCREATE HERE EQU <DOCREATE>
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<n2, signed
S ,++ SUBD, TOSTRUE BGT, CLRA, CLRB, NEXT ;C
CODE > \ n1 n2 -- flag test n1>n2, signed
S ,++ SUBD, TOSTRUE BLT, CLRA, CLRB, NEXT ;C
CODE U< \ n1 n2 -- flag test n1<n2, unsigned
S ,++ SUBD, TOSTRUE BHI, CLRA, CLRB, NEXT ;C
CODE U> \ 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 <DOCOLON> ,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 <DODOES>
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, <DODOES> ,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
<DOCREATE> ,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<=n1<n3?
OVER - >R - 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.