\ (2) 07dec2005
\ (1) 12jul2005
\ MAIS AN601 TARGET CODE -- Albert Nijhof -- 06jun2005
<----
:::MAIS::: (the metacompiler)
|
executes the red words and
compiles the blue words.
Numbers are grey-white.
Green text is handled by
the preceding red word.
|
|
:::MAIS::: (de metacompiler)
|
voert de rode woorden uit en
compileert de blauwe woorden.
Getallen zijn grijswit.
Groene tekst wordt afgehandeld
door het voorafgaande rode woord.
|
---->
HX 65 TO USERBYTES
\ HX 2000 TO ORIGINTARGA
NOTRACE
HEX \ throughout
<----
Put a TRACE before and a NOTRACE after a piece of code if you
wish to study the details of what happens when that code is metacompiled.
Zet TRACE voor en NOTRACE achter een stukje code als je wilt
bekijken wat er gebeurt tijdens het metacompileren van die code.
-- Direct-Threaded Forth model for Motorola 6809
16 bit cell, 8 bit char, 8 bit (byte) adrs unit
X = Forth W free
Y = IP Interpreter Pointer
U = RP Return Stack Pointer
S = SP Data Stack Pointer
D = TOS Top of data stack
-- m e m o r y m a p
hex
00~ 75 "USER Page"
--- ---
00 JMP COLD
03 Dictionary with hx 10 topnfas
23-75 Cold start data: space available
for up to 32 users(64 bytes)
and 6 vectors(18 bytes)
--- ---
75~ 80 Search order stack (CONTEXT..CURRENT)
80~100 TIB (hx 80 bytes)
100~180 Data stack (hx 80 bytes)
180~200 Return stack (hx 80 bytes)
200~280 Fly zone
280~300 Compiler stack
300 = HERE at Cold Start
--- --- moving up:
HERE ~ Ruimte voor BL-WORD (hx 20 bytes)
~ PAD HOLD Buffer (hx 20 bytes) (dalend)
PAD = HERE + hx 40
--- ---
HIMEM = Einde van de RAM
-- TOPNFA = NFA of the most recently created Word
-- Four linked lists:
Links point to the zero-labeled positions (see below).
End of List is reached when Link=0
1) Words
hx 10 Topnfa's (Threads) of the dictionary,
in RAM: hx (03~23), in ROM: ORIGIN+(03~23).
Word map (there is a Homlink only if Name is a homonym).
| Homlink | Link | Homvocimm | Count + Name | Cf | Body
-5 -3 -1 0 1 n+1 n+4
2) Wordlists
TOPVOC = Address of most recently created Wordlist.
Wordlist (usually situated in a Vocabulary body)
| Wid | Link |
0 1 3
3) THROW Messages
TOPMSG = Address of most recently created Message.
Message
| Msg# | Link | Count + Text |
0 2 4 5 n+5
4) Prefixlists
TOPPFX = Address of most recently created Prefixlist.
Prefixlist
| Link | doer-token | TO-action | +TO-action | INCR-action |
-2 0 2 4 6 8
-- NEXT == Y )++ [] JMP \ ip )++ ) jump
-- Interrupt vectors
'SWI3 'SWI2 'FIRQ 'IRQ 'SWI 'NMI (3 bytes each)
'SWI3 ( -- adr ) \ adr = FFF2 @
'SWI2 ( -- adr ) \ adr = FFF4 @
'FIRQ ( -- adr ) \ adr = FFF6 @
'IRQ ( -- adr ) \ adr = FFF8 @
'SWI ( -- adr ) \ adr = FFFA @
'NMI ( -- adr ) \ adr = FFFC @
Default contents of these addresses: 3B 00 00 (3B = RTI).
: !VECTOR ( routineaddress vector -- ) 1+ ! ;
: ENABLE ( vector -- ) 07E SWAP C! ;
: DISABLE ( vector -- ) 03B SWAP C! ;
Example of use:
1AF0 'SWI3 !VECTOR \ Address of interrupt routine into byte 2 en 3.
'SWI3 ENABLE \ 7E = JMP into byte 1.
'SWI3 DISABLE \ 3B = RTI into byte 1.
MaisForth Target code:
---->
:::MAIS:::
\ ----- 01 ----- cold start data
0 JMP \ for JMP COLD -- See COLD ttt
DICTIONARY \ 0003-0023 ttt
I-DATA \ Space reservation for cold users values ttt See USERBYTES in META
\ At cold start the ROM data until here (C000-C0..)
\ will be copied to RAM (00-..)
\ ----- 02 ----- doers
FORTH:
CODE EXECUTE D X TFR REG D PULS X ) JMP END-CODE
CODE EXIT REG Y PULU NEXT END-CODE
INSIDE:
CODE EXIT-ON-TRUE ( flag -- )
0 # CMPD REG D PULS =? NO IF REG Y PULU THEN NEXT END-CODE
CODE EXIT-ON-FALSE ( flag -- )
0 # CMPD REG D PULS =? IF REG Y PULU THEN NEXT END-CODE
CODE DIVE ( -- ) \ See FLYER PARENTHESIZE
Y X TFR REG Y PULU REG X PSHU NEXT END-CODE
CODE DODOES \ (an) 2004
REG Y PSHU \ save IP
REG Y PULS \ new IP = returnaddress = just after JSR DODOES
REG X PULS REG D PSHS X D TFR ( body ? -- ? body )
NEXT END-CODE
DOER: DODOER HERE-IS THINGUMAJIG EXIT ;
\ Voorwaartse referentie. De EXIT wordt later gepatcht. Zie !DOER
\ Het uiteindelijke resultaat: DOER: DODOER !DOER ;
DOERCODE DO: REG Y PSHU REG Y PULS NEXT END-CODE
DOERCODE DOCREATE REG X PULS REG D PSHS X D TFR NEXT END-CODE
DOERCODE DOVAR REG X PULS REG D PSHS X D TFR NEXT END-CODE
DOERCODE DOCCON REG X PULS REG D PSHS X ) LDB SEX NEXT END-CODE \ C@
DOERCODE DOCON REG X PULS REG D PSHS X ) LDD NEXT END-CODE \ @
DOERCODE DOVAL REG X PULS REG D PSHS X ) LDD NEXT END-CODE \ @
DOERCODE DOIVAR REG X PULS REG D PSHS X ) LDD NEXT END-CODE \ @
DOERCODE DOIVAL REG X PULS REG D PSHS X ) [] LDD NEXT END-CODE \ @@
DOERCODE DOVARS ASLB ROLA S )++ ADDD NEXT END-CODE \ SWAP CELLS +
\ ----- 03 ----- input output
\ Input and output for the MAIS board. (FvdM) 2003 ttt
<----
USART +0 DATA
+1 STATUS
+2 MODE
+3 COMMAND
---->
FORTH:
CODE EMIT? ( -- flag )
REG D PSHS USART 1 + LDA CLRB \ STATUS C@ 1 AND 1 =
1 # ANDA =? NO IF DECB THEN
SEX NEXT END-CODE
INSIDE:
CODE (EMIT ( char -- )
USART # LDX
BEGIN X 1 #) LDA 1 # ANDA =? NO UNTIL \ STATUS C@ 1 AND UNTIL
X ) STB REG D PULS NEXT END-CODE \ CH DATA C!
EXTRA:
CODE !USART ( baudbyte -- ) \ Set up on-board i/o, See COLD
USART # LDX X 3 #) LDA \ read command reg. to reset mode
4E # LDA X 2 #) STA \ set mode register 1
( Baudbyte ) X 2 #) STB \ set mode register 2 (BAUD)
15 # LDA X 3 #) STA \ set command register
REG D PULS NEXT END-CODE
FORTH:
CODE KEY? ( -- flag )
REG D PSHS USART 1 + LDA CLRB \ STATUS C@ 2 AND 2 =
2 # ANDA =? NO IF DECB THEN
SEX NEXT END-CODE
CODE KEY ( -- char )
REG D PSHS USART # LDX
BEGIN X 1 #) LDB 2 # ANDB =? NO UNTIL \ STATUS C@ 2 AND UNTIL
X ) LDB CLRA NEXT END-CODE \ DATA C@
\ ----- 04 ----- inline arguments
\ Inline arguments (AN) 2004
\ To be used in hi-level definitions:
INSIDE:
CODE INLINE# ( -- x ) \ See COMPILE() TO$() +TO$() INCR$()
REG D PSHS
U ) LDX \ R@
X )++ LDD \ inline#
U ) STX \ skip
NEXT END-CODE
<----
CODE INLINEC ( -- x ) \ Inline byte
REG D PSHS
U ) LDX \ R@
X )+ LDB CLRA \ inline#
U ) STX \ skip
NEXT END-CODE
---->
CODE INLINE$ ( -- adr len ) \ See "(S) ."(S)
REG D PSHS
U ) LDX \ R@
X )+ LDB CLRA \ C@ (=len)
REG X PSHS \ adr
ABX U ) STX \ skip
NEXT END-CODE
CODE /INLINE$ ( -- ) \ See ABORT"(S)
REG D PSHS
U ) LDX \ R@
X )+ LDB \ C@ (=len)
X B) LEAX U ) STX \ skip
REG D PULS NEXT END-CODE
\ Words that need inline arguments (an)
INSIDE:
CODE GOTO() ( -- ) \ branch always. See AHEAD AGAIN
Y ) LDY NEXT END-CODE
CODE IF() ( x -- ) \ branch on zero.
0 # CMPD REG D PULS =?
IF Y ) LDY NEXT
THEN Y 2 #) LEAY NEXT END-CODE
CODE IFZERO() ( x -- ) \ branch on non-zero. See IF & <FUSE
0 # CMPD REG D PULS =? NO
IF Y ) LDY NEXT
THEN Y 2 #) LEAY NEXT END-CODE
CODE () ( -- x ) REG D PSHS Y )++ LDD NEXT END-CODE \ See LITERAL
CODE (C) ( -- ch ) REG D PSHS Y )+ LDB SEX NEXT END-CODE \ See LITERAL
\ Prefixes - See TO-LIST
INSIDE:
CODE TO() ( x -- ) Y )++ LDX X ) STD REG D PULS NEXT END-CODE
CODE +TO() ( x -- ) Y )++ LDX X ) ADDD X ) STD REG D PULS NEXT END-CODE
CODE INCR() ( -- ) Y )++ LDX REG D PSHS
X ) LDD 1 # ADDD X ) STD REG D PULS NEXT END-CODE
\ DO LOOP (AN) 2004
\ --- A'DAM
INSIDE:
CODE DO() ( limit start -- ) \ R: leavea 8000-lim start+8000-lim
HERE-IS AMSTERDAM
Y )++ LDX REG X PSHU \ inline leave address >R
D X TFR \ start
8000 # LDD S )++ SUBD \ 8000-limit
REG D PSHU \ >r
X D) LEAX REG X PSHU \ start+8000-limit >r
REG D PULS \ new top
NEXT END-CODE
CODE ?DO() ( limit start -- ) \ R: leavea 8000-lim start+8000-lim
S ) CMPD AMSTERDAM BNE
S 2 #) LEAS REG D PULS \ 2DROP
Y ) LDY NEXT END-CODE \ leave address to IP
\ ---
\ --- R'DAM
INSIDE:
CODE LOOP() \ R: leavea 8000-lim start+8000-lim
REG D PSHS U ) LDD \ r>
1 # ADDD
HERE-IS ROTTERDAM
VS? NO
IF U ) STD REG D PULS \ >r
Y ) LDY NEXT \ loop again
THEN \ overflow:
Y 2 #) LEAY \ loop ready
U 6 #) LEAU \ RDROP RDROP RDROP
REG D PULS \ new top
NEXT END-CODE
CODE +LOOP() ( n -- ) \ R: leavea 8000-lim start+8000-lim
U ) ADDD \ top u) + to top
ROTTERDAM BRA
END-CODE
\ ---
FORTH:
CODE LEAVE ( -- ) \ R: leavea 8000-lim start+8000-lim
U 4 #) LEAU \ RDROP RDROP
REG Y PULU \ R> TO IP
NEXT END-CODE
CODE UNLOOP ( -- ) \ R: leavea 8000-lim start+8000-lim
U 6 #) LEAU \ RDROP RDROP RDROP
NEXT END-CODE
CODE I ( -- i ) REG D PSHS U ) LDD U 2 #) SUBD NEXT END-CODE
CODE J ( -- j ) REG D PSHS U 6 #) LDD U 8 #) SUBD NEXT END-CODE
\ ----- 05 ----- ttt
<----
IVAL en IVAR
de I staat voor indirectie. De "userpage" begint op 0000.
Eerst een jump naar COLD, dan 16 draden (03-023)
De koude offset t.o.v. ORIGIN is dus tevens warm RAM adres.
IVAL gedraagt zich als een value. Het systeem kan hem veranderen,
de programmeur kan dat niet rechtstreeks:
---->
\ indirecte values (an)
\ De programmeur kan deze grootheden alleen indirect wijzigen.
\ The programmer can only indirectly change these system values.
INSIDE: 0 IVAL TOPVOC \ See WORDLIST VOC>NAMA (FORGET
0 IVAL TOPMSG \ See MSG" .MSG (FORGET
0 IVAL TOPPFX \ See O&P TO +TO INCR
303 IVAL TOPNFA \ Last created header in dictionary.
0 IVAL HLD \ See HOLD <# #>
0 IVAL CONTEXT \
01F IVAL CS# \ Relatieve CS-pointer. See CSP >CS CS>
0 IVAL MSG#-2 \ See ABORT"(S) .MSG
30 IVAL MODE \ Assembler adressing mode:
\ 0=immed, 10=direct, 20=indexed, 30=extended
0 IVAL SECTION \ Marks compiler discontinuity (for 0=IF)
0 IVAL #TIMES \ See TIMES
0 IVAL #IB \ Inputbuffer len
0 IVAL IB \ Inputbuffer adr
200 IVAL THERE \ Tijdelijke HERE -- See FLYER
EXTRA: 0 IVAL HOR \ Telt karakter output, 0 = begin vd regel.
0 IVAL VER \
0 IVAL HIMEM \ hoogste RAMadres+1
3 IVAL OK \ See .OK
0 IVAL DOT? \ See DNUMBER? EVAL
FORTH: 300 IVAL HERE \ See ALLOT
\ indirecte variabelen
INSIDE: 0 IVAR WRD 2 UALLOT \ see WORD
FORTH: 0 IVAR >IN \ ( -- adr )
0A IVAR BASE \ ( -- adr )
0 IVAR STATE \ ( -- adr )
\ Interrupt en Exception vectoren.
\ De pointers in FFF0-FFFF wijzen naar deze adressen.
EXTRA:
\ For ROM version
\ Interrupt vectors FFF0,FFF2,FFF4,FFF6,FFF8,FFFA,FFFC.
ORIGINHOSTA -10 + \ later: FFF0
ORIGINTARGA OVER !
2 + UOFFSET OVER ! IVEC 'SWI3 \ FFF2
2 + UOFFSET OVER ! IVEC 'SWI2 \ FFF4
2 + UOFFSET OVER ! IVEC 'FIRQ \ FFF6
2 + UOFFSET OVER ! IVEC 'IRQ \ FFF8
2 + UOFFSET OVER ! IVEC 'SWI \ FFFA
2 + UOFFSET OVER ! IVEC 'NMI \ FFFC
DROP -2 UALLOT \ Alleen de byte met RTI wordt meegenomen.
\ Een vector neemt 3 userbytes ruimte in.
\ 'NMI is de laatste "user"!
\ Als je meer indirecte waarden wilt definiëren, voeg die dan in
\ voor de vectoren. De value USERBYTES in de metacompiler moet
\ dan aangepast worden:
\ userbytes = (aantal i-waarden)*2 + (aantal vectoren)*3 - 2
\ --- constanten ---
FORTH:
ORIGINTARGA CONSTANT ORIGIN \ ttt
INSIDE: 075 CONSTANT FINDSTACK \ Begin of search-order stack
07F CONSTANT CURRENT \ End of search-order stack
080 CONSTANT TIB \ Terminal Input Buffer
17E CONSTANT S0 \ End of parameter stack
1FE CONSTANT R0 \ End of return stack
200 CONSTANT FLYBUF \ Flyer buffer
2FC CONSTANT CS0 \ End of compilerstack
07E CONSTANT TIBSIZE
EXTRA: 2 CONSTANT CELL
FORTH: -1 CONSTANT TRUE
0 CONSTANT FALSE
20 CONSTANT BL
\ ----- 06 -----
\ memory operations
INSIDE:
CODE CLEAR-S ' S0 >body @ # LDS REG D PULS NEXT END-CODE \ See QUIT
CODE CLEAR-R ' R0 >body @ # LDU NEXT END-CODE \ See QUIT
\ Get stack-pointer
CODE SP@ REG D PSHS S D TFR NEXT END-CODE \ ?STACK DEPTH
CODE RP@ REG D PSHS U D TFR NEXT END-CODE \ Not used
\ CODE SP! D S TFR REG D PULS NEXT END-CODE \ Not used
\ CODE RP! D U TFR REG D PULS NEXT END-CODE \ Not used
\ Store en Fetch
FORTH:
CODE C! D X TFR REG D PULS X ) STB REG D PULS NEXT END-CODE
CODE ! D X TFR REG D PULS X ) STD REG D PULS NEXT END-CODE
CODE 2! D X TFR REG D PULS
X )++ STD REG D PULS X ) STD REG D PULS NEXT END-CODE
CODE +! D X TFR REG D PULS
X ) ADDD X ) STD REG D PULS NEXT END-CODE
EXTRA:
CODE C+! D X TFR REG D PULS
X ) ADDB X ) STB REG D PULS NEXT END-CODE
CODE 1+! D X TFR X ) LDD
1 # ADDD X ) STD REG D PULS NEXT END-CODE
FORTH:
CODE C@ D X TFR X ) LDB CLRA NEXT END-CODE
CODE @ D X TFR X ) LDD NEXT END-CODE
CODE 2@ D X TFR X )++ LDD X ) LDX REG X PSHS NEXT END-CODE
CODE COUNT D X TFR X )+ LDB CLRA REG X PSHS NEXT END-CODE
EXTRA:
CODE @+ D X TFR X )++ LDD REG X PSHS NEXT END-CODE
\ Return stack
FORTH:
CODE >R REG D PSHU REG D PULS NEXT END-CODE
CODE R> REG D PSHS REG D PULU NEXT END-CODE
CODE 2>R REG X PULS REG X PSHU REG D PSHU REG D PULS NEXT END-CODE
CODE 2R> REG D PSHS REG D PULU REG X PULU REG X PSHS NEXT END-CODE
CODE R@ REG D PSHS U ) LDD NEXT END-CODE
CODE 2R@ REG D PSHS U 2 #) LDX REG X PSHS U ) LDD NEXT END-CODE
EXTRA:
CODE RDROP U 2 #) LEAU NEXT END-CODE
CODE 2RDROP U 4 #) LEAU NEXT END-CODE
<---- \ Double exit:
INSIDE:
CODE DEXIT ( -- ) REG X,Y PULU NEXT END-CODE \ Same as RDROP+EXIT
---->
\ stack operations
FORTH:
CODE 2DROP S 2 #) LEAS REG D PULS NEXT END-CODE
CODE 2DUP S ) LDX REG D PSHS REG X PSHS NEXT END-CODE
CODE 2NIP REG X PULS S 4 #) LEAS REG X PSHS NEXT END-CODE
CODE 2OVER REG D PSHS S 6 #) LDD REG D PSHS S 6 #) LDD NEXT END-CODE
CODE 2SWAP REG D PSHU S ) LDX S 4 #) LDD S 4 #) STX S ) STD \ swap n2 n4:
REG X PULU S 2 #) LDD S 2 #) STX NEXT END-CODE \ swap n1 n3
: 2TUCK 2SWAP 2OVER ; ( x1 x2 x3 x4 -- x3 x4 x1 x2 x3 x4 )
: 2ROT 2>R 2SWAP 2R> 2SWAP ;
\ : -2ROT 2SWAP 2>R 2SWAP 2R> ;
<----
CODE 2TUCK ...
CODE 2ROT ...
---->
FORTH:
CODE ?DUP 0 # CMPD =? NO IF REG D PSHS THEN NEXT END-CODE
CODE DROP REG D PULS NEXT END-CODE
CODE DUP REG D PSHS NEXT END-CODE
CODE OVER REG D PSHS S 2 #) LDD NEXT END-CODE
CODE SWAP S ) LDX S ) STD X D TFR NEXT END-CODE
CODE TUCK S ) LDX S ) STD REG X PSHS NEXT END-CODE
CODE ROT S ) LDX S ) STD S 2 #) LDD S 2 #) STX NEXT END-CODE
CODE -ROT S 2 #) LDX S 2 #) STD S ) LDD S ) STX NEXT END-CODE
\ --- A'DAM
FORTH:
CODE NIP HERE-IS AMSTERDAM S 2 #) LEAS NEXT END-CODE
CODE PICK ASLB S X TFR ABX X ) LDD NEXT END-CODE
CODE MIN S ) CMPD AMSTERDAM BLT REG D PULS NEXT END-CODE
CODE MAX S ) CMPD AMSTERDAM BGT REG D PULS NEXT END-CODE
EXTRA:
CODE UMIN S ) CMPD AMSTERDAM BLO REG D PULS NEXT END-CODE
CODE UMAX S ) CMPD AMSTERDAM BHI REG D PULS NEXT END-CODE
\ ---
\ comparison operations (an)
FORTH:
CODE 0< A B TFR SEX A B TFR NEXT END-CODE
\ --- R'DAM
FORTH:
CODE 0= 0 # CMPD =?
IF HERE-IS ROTTERDAM COMB SEX NEXT \ B=0 -> D=-1.
THEN CLRA CLRB NEXT END-CODE
CODE 0> 0 # CMPD =? IF NEXT THEN
A B TFR SEX COMA A B TFR NEXT END-CODE
CODE = S )++ SUBD ROTTERDAM BEQ CLRA CLRB NEXT END-CODE
\ ---
\ --- A'DAM
FORTH:
CODE <> S )++ SUBD =? NO IF HERE-IS AMSTERDAM -1 # LDD THEN NEXT END-CODE
CODE 0<> 0 # CMPD AMSTERDAM BNE NEXT END-CODE
CODE U> S )++ SUBD AMSTERDAM BLO CLRA CLRB NEXT END-CODE
CODE U< S )++ SUBD AMSTERDAM BHI CLRA CLRB NEXT END-CODE
CODE > S )++ SUBD AMSTERDAM BLT CLRA CLRB NEXT END-CODE
CODE < S )++ SUBD AMSTERDAM BGT CLRA CLRB NEXT END-CODE
<----
EXTRA: \ (FvdM) 2004
CODE 0>= TSTA AMSTERDAM BPL CLRA CLRB NEXT END-CODE
CODE <= S )++ SUBD AMSTERDAM BGE CLRA CLRB NEXT END-CODE
CODE >= S )++ SUBD AMSTERDAM BLE CLRA CLRB NEXT END-CODE
CODE U<= S )++ SUBD AMSTERDAM BHS CLRA CLRB NEXT END-CODE
CODE U>= S )++ SUBD AMSTERDAM BLS CLRA CLRB NEXT END-CODE
---->
\ ---
\ logical operations
FORTH:
CODE AND S )+ ANDA S )+ ANDB NEXT END-CODE
CODE OR S )+ ORA S )+ ORB NEXT END-CODE
CODE XOR S )+ EORA S )+ EORB NEXT END-CODE
CODE INVERT COMA COMB NEXT END-CODE
CODE LSHIFT \ bjr
D X TFR REG D PULS X ) LEAX =? NO
IF BEGIN LSLB ROLA X -1 #) LEAX =?
UNTIL
THEN NEXT END-CODE
CODE RSHIFT \ bjr
D X TFR REG D PULS X ) LEAX =? NO
IF BEGIN LSRA RORB X -1 #) LEAX =?
UNTIL
THEN NEXT END-CODE
EXTRA:
CODE BYTESWAP ( swap bytes ) A B EXG NEXT END-CODE
\ arithmetic operations
FORTH:
CODE 1+ 1 # ADDD NEXT END-CODE
CODE 1- 1 # SUBD NEXT END-CODE
CODE 2* ASLB ROLA NEXT END-CODE
CODE 2/ ASRA RORB NEXT END-CODE \ arithmetic right shift
CODE + S )++ ADDD NEXT END-CODE
CODE - S )++ SUBD COMA COMB 1 # ADDD NEXT END-CODE
CODE D2* D X TFR REG D PULS ASLB ROLA
REG D PSHS X D TFR ROLB ROLA NEXT END-CODE
\ --- A'DAM
FORTH:
CODE D2/ ASRA
HERE-IS AMSTERDAM
RORB D X TFR REG D PULS
RORA RORB REG D PSHS X D TFR NEXT END-CODE
EXTRA:
CODE DU2/ LSRA AMSTERDAM BRA NEXT END-CODE
\ ---
\ --- R'DAM
FORTH:
CODE NEGATE HERE-IS ROTTERDAM COMA COMB 1 # ADDD NEXT END-CODE
CODE ABS TSTA ROTTERDAM BLT NEXT END-CODE
EXTRA:
CODE ?NEGATE TSTA REG D PULS ROTTERDAM BLT NEXT END-CODE
<----
\ : ABS DUP ?NEGATE ;
\ : ?NEGATE ( x1 y -- x2 ) 0< 0= ?EXIT NEGATE ;
---->
\ ---
\ --- R'DAM
FORTH:
CODE DNEGATE ( xlo xhi -- ylo yhi ) \ (AN) 2004
HERE-IS ROTTERDAM
REG D PSHS
CLRB SEX D X TFR \ 0
S 2 #) SUBD S 2 #) STD \ ylo
X D TFR 0 # SBCB SEX \ 0 -carry?
S )++ SUBD \ yhi
NEXT END-CODE
CODE DABS TSTA ROTTERDAM BLT NEXT END-CODE
EXTRA:
CODE ?DNEGATE TSTA REG D PULS ROTTERDAM BLT NEXT END-CODE
<----
\ : DABS DUP ?DNEGATE ;
EXTRA:
\ : ?DNEGATE ( xlo xhi y -- xlo2 xhi2 ) 0< 0= ?EXIT DNEGATE ;
---->
\ ---
FORTH:
CODE D+ ( dx dy -- dz ) \ (AN) 2004
D X TFR \ yhi
REG D PULS \ ylo
S 2 #) ADDD \ xlo +to ylo
S 2 #) STD \ = zlo
X D TFR \ yhi
0 # ADCB 0 # ADCA \ yhi + carry?
S )++ ADDD \ xhi +to yhi = zhi
NEXT END-CODE
CODE D- ( xlo xhi ylo yhi -- zlo zhi ) \ (AN) 2004
REG D PSHS
S 6 #) LDD S 2 #) SUBD S 6 #) STD \ zlo
S 4 #) LDD 0 # SBCB 0 # SBCA \ xhi -carry?
S ) SUBD \ zhi
S 6 #) LEAS NEXT END-CODE
CODE M+ ( dx ylo -- dz )
S 2 #) ADDD \ xlo +to ylo
S 2 #) STD \ = zlo
REG D PULS \ xhi
0 # ADCB 0 # ADCA \ xhi + carry?
NEXT END-CODE
CODE UM* ( u1 u2 -- ud ) \ 16*16=32 unsigned multiply (c) 25apr95 bjr
REG 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 ) LDB MUL \ 1lo*2hi
S 1 #) ADDD S 1 #) STD 0 # LDA ROLA \ cy in A
S ) LDB S ) STA S 4 #) LDA MUL \ 2hi*1hi
S ) ADDD \ hi result in D
S 2 #) LDX S 4 #) LEAS S ) STX NEXT END-CODE \ lo result
CODE UM/MOD ( ud u1 -- rem quot ) \ 32/16=16 divide (c) 25apr95 bjr
REG D 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 ) SUBD S 2 #) STD 0FE # ANDCC \ clear cy
ELSE \ 0xxxx: 16 bits, test subtract
S ) SUBD CS? NO 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
=? 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 END-CODE
\ string operations
CODE FILL ( c-addr u char -- ) \ (c) 31mar95 bjr
REG Y PSHU REG X,Y PULS \ D=char X=u Y=adr
0 # CMPX =? NO
IF BEGIN Y )+ STB X -1 #) LEAX =?
UNTIL
THEN REG D PULS REG Y PULU NEXT END-CODE
EXTRA:
CODE S<> ( a1 a2 len -- -1 | 1 | 0 ) \ string compare
S 2 #) ADDD S 2 #) LDX S 2 #) STY \ X=src D=end
S ) LDY S ) STD CLRB \ Y=dst B=0
AHEAD
BEGIN X )+ LDA Y )+ SUBA =? NO
IF 0 # SBCB SEX 1 # ORB
REG X,Y PULS NEXT
THEN
/THEN S ) CMPX =?
UNTIL
SEX REG X,Y PULS NEXT END-CODE
FORTH:
CODE CMOVE ( c-addr1 c-addr2 u -- ) \ BJR*
S 2 #) ADDD S 2 #) LDX S 2 #) STY \ X=src D=end
S ) LDY S ) STD \ Y=dst
AHEAD
BEGIN X )+ LDB Y )+ STB
/THEN S ) CMPX =?
UNTIL REG X,Y PULS REG D PULS
NEXT END-CODE
CODE CMOVE> ( c-addr1 c-addr2 u -- ) \ BJR*
S 2 #) LDX X D) LEAX S 2 #) STY \ X=src D=u
S ) LDY Y D) LEAY \ Y=dst
AHEAD
BEGIN X -) LDB Y -) STB
/THEN S ) CMPY =?
UNTIL
REG X,Y PULS REG D PULS
NEXT
\ Exits for SKIP en SCAN (hereafter)
\ --- A'DAM & R'DAM
HERE-IS AMSTERDAM Y -1 #) LEAY
HERE-IS ROTTERDAM REG Y PSHS REG Y PULU X D TFR
NEXT END-CODE
EXTRA:
CODE SKIP ( c-addr u ch -- c-addr' u' ) \ skip matching chars BJR
REG Y PSHU REG X,Y PULS \ D=char X=u Y=adr
0 # CMPX =? NO
IF BEGIN Y )+ CMPB AMSTERDAM BNE
X -1 #) LEAX =?
UNTIL
THEN ROTTERDAM BRA END-CODE
CODE SCAN ( c-addr u ch -- c-addr' u' ) \ find matching char BJR
REG Y PSHU REG X,Y PULS \ D=char X=u Y=adr
0 # CMPX =? NO
IF BEGIN Y )+ CMPB AMSTERDAM BEQ
X -1 #) LEAX =?
UNTIL
THEN ROTTERDAM BRA END-CODE
\ ---
\ ----- 07 -----
FORTH:
\ CODE ALIGNED ( a -- a ) NEXT END-CODE IMMEDIATE
\ CODE ALIGN ( -- ) NEXT END-CODE IMMEDIATE
CODE CELL+ 2 # ADDD NEXT END-CODE
CODE CHAR+ 1 # ADDD NEXT END-CODE
CODE >BODY 3 # ADDD NEXT END-CODE
EXTRA:
CODE CELL- 2 # SUBD NEXT END-CODE
CODE CHAR- 1 # SUBD NEXT END-CODE
CODE BODY> 3 # SUBD NEXT END-CODE
FORTH:
CODE CELLS ASLB ROLA NEXT END-CODE
CODE CHARS NEXT END-CODE IMMEDIATE
INSIDE:
CODE NAME>LINK ( nfa -- lfa ) 3 # SUBD NEXT END-CODE
FORTH:
: ROLL ( n -- x )
>R R@ PICK
SP@ DUP CELL+ R> 1+ CELLS CMOVE>
DROP ;
: PAD HERE 40 + ;
: ALLOT +TO HERE ;
: , HERE ! CELL +TO HERE ;
: C, HERE C! INCR HERE ;
EXTRA:
\ : NAME> ( nfa -- xt ) COUNT 1F AND + ;
\ : >NAME ( cfa -- nfa ) BEGIN 1- 60 OVER C@ AND 0= UNTIL ;
CODE NAME> D X TFR X )+ LDB 1F # ANDB X B) LEAX X D TFR NEXT END-CODE
CODE >NAME D X TFR
BEGIN 60 # LDB X -) ANDB =?
UNTIL
X D TFR NEXT END-CODE
INSIDE:
: !DOER ( DOERa -- ) TOPNFA NAME> 1+ ! ; \ de JSR staat er al
' !DOER THINGUMAJIG COMPILE! \ Patch in DODOER (Voorwaartse referentie)
\ : @IMM ( nfa -- -1/+1 ) 1- C@ 1 AND 2* 1- ;
\ : HOM? ( nfa -- 0/-1 ) 1- C@ 80 AND 0<> ;
\ : @VOC ( nfa -- wid ) 1- C@ 7E AND ;
CODE @IMM D X TFR X -) LDB 1 # ANDB ASLB DECB SEX NEXT END-CODE
CODE HOM? D X TFR X -) LDB SEX A B TFR NEXT END-CODE
CODE @VOC D X TFR X -) LDB 7E # ANDB SEX NEXT END-CODE
FORTH:
\ : WITHIN ( a x y -- flag ) OVER - >R - R> U< ;
CODE WITHIN ( a x y -- t/f ) \ a-x y-x u<?
S ) SUBD D X TFR \ y-x
S 2 #) LDD S )++ SUBD \ a-x
S ) STX S )++ SUBD \ a-x - y-x
0 # LDB \ dit beinvloedt U<? niet?
U<? IF DECB THEN SEX NEXT END-CODE
\ ----- 08 -----
\ Compilerstack [HIMEM-80..HIMEM) (dalend) (AN) 2004
INSIDE:
: CSP ( -- a ) CS0 CS# CELLS 2* 7C AND - ;
: >CS ( x1 x2 -- ) INCR CS# CSP 2! ;
: CS> ( -- x1 x2 ) CSP 2@ -1 +TO CS# ;
FORTH:
: CS-PICK ( n -- )
CS# >R
NEGATE +TO CS# CS>
R> TO CS# >CS ;
: CS-ROLL ( q -- ) \ q in 0..1F
>R
R@ 0 ?DO CS> LOOP \ Haal elementen 0..n-1 van CS-stack
R> CS> 2>R \ Verplaats element nr n van CS-stack naar R
0 ?DO >CS LOOP \ Zet elementen n-1..0 terug op CS-stack
2R> >CS ; \ Verplaats element nr n van R naar CS-stack
FORTH:
\ : S>D DUP 0< ;
CODE S>D REG D PSHS A B TFR SEX A B TFR NEXT END-CODE
<----
: M* ( n1 n2 -- d ) \ signed 16*16->32 multiply (BJR)
2DUP XOR >R
SWAP ABS SWAP ABS UM* \ eerste SWAP kan weg
R> ?DNEGATE ;
: SM/REM ( d1 n1 -- n2 n3 ) \ symmetric signed division (BJR)
2DUP XOR >R
OVER >R \ Dhi
ABS >R DABS R> UM/MOD
SWAP R> ?NEGATE
SWAP R> ?NEGATE ;
: FM/MOD ( d1 n1 -- n2 n3 ) \ floored signed division (BJR)
DUP >R 2DUP XOR >R >R
DABS R@ ABS UM/MOD SWAP
R> ?NEGATE SWAP R> 0<
IF NEGATE OVER \ quotient negative
IF \ if remainder nonzero
R@ ROT - SWAP 1- \ adjust rem,quot
THEN
THEN RDROP ;
---->
: M* ( n1 n2 -- d ) \ signed 16*16->32 (AN)
OVER ABS OVER ABS UM*
2SWAP XOR ?DNEGATE ;
: SM/REM ( d n -- r q ) \ symmetric signed (AN)
OVER >R >R \ R: Dhi n
DABS R@ ABS UM/MOD ( r q )
R> R@ XOR ?NEGATE SWAP
R> ?NEGATE SWAP ; \ Dhi neg?
: FM/MOD ( d1 n1 -- n2 n3 ) \ floored signed (AN)
>R TUCK \ dhi dlo dhi r: n
DABS R@ ABS UM/MOD \ dhi r q
SWAP R@ ?NEGATE \ dhi q r*
SWAP ROT R@ XOR 0< \ r q neg?
IF NEGATE OVER \ r q* r
IF 1- \ r q-1
R@ ROT - SWAP \ n-r q-1
THEN
THEN RDROP ;
: * M* DROP ;
: /MOD >R S>D R> FM/MOD ;
: / /MOD NIP ;
: MOD /MOD DROP ;
: */MOD >R M* R> FM/MOD ;
: */ */MOD NIP ;
\ input/output
\ ----- 09 -----
FORTH:
: EMIT ( c -- ) (EMIT INCR HOR ;
: CR ( -- ) 0D (EMIT 0A (EMIT FALSE TO HOR INCR VER ;
: SPACE ( -- ) BL EMIT ;
: SPACES ( n -- ) BL SWAP 0 ?DO DUP EMIT LOOP DROP ;
: TYPE ( a n -- ) 0 ?DO COUNT EMIT LOOP DROP ;
: PAGE ( -- ) 0C EMIT FALSE TO HOR FALSE TO VER ;
EXTRA:
: BACKSPACE ( -- )
HOR 0= ?EXIT
8 BL OVER (EMIT (EMIT (EMIT -1 +TO HOR ;
INSIDE:
: ACCEPTING ( n a i - i ) \ n a i n=imax, a=adr, i=count
KEY \ n a i ch
DUP BL <
IF
0D OVER = IF 2NIP DROP } \ i char=CR: ready, leave ACCEPTING
8 = IF DUP IF BACKSPACE 1- THEN RE} \ n a i- destructive backspace when i<>0
BL \ n a i bl ctrl char is replaced by BL
THEN
OVER 4 PICK = IF DROP RE} \ n a i i=n: no action
DUP 2OVER + C! EMIT 1+ RE (;) \ n a i+ store and emit
FORTH:
: ACCEPT ( a n -- i ) \ i=teller (AN) 2004
SWAP FALSE \ n a i n=imax, a=adr, i=count
ACCEPTING ;
EXTRA:
<----
: DU/MOD ( ud1 u2 -- u3 ud4 ) \ 32/16->32 divide (BJR)
>R 0 R@ UM/MOD
ROT ROT R> UM/MOD ROT ;
: DU* ( ud1 u2 -- ud3 ) \ 32*16->32 multiply (BJR)
DUP >R UM* DROP SWAP R> UM* ROT + ;
---->
: DU/MOD ( ud1 u2 -- u3 ud4 ) \ 32/16->r=16,q=32 (AN)
TUCK FALSE SWAP UM/MOD >R SWAP UM/MOD R> ;
: DU* ( ud1 u2 -- ud3 ) \ 32*16->32 (AN)
TUCK UM* DROP >R UM* R> + ;
FORTH:
: HOLD -1 +TO HLD HLD C! ; ( char -- ) \ add char to output string
: <# PAD TO HLD ; ( -- ) \ begin numeric conversion
INSIDE:
: >DIGIT ( x -- char ) DUP 9 > 7 AND + 30 + ;
FORTH:
: # BASE @ DU/MOD ROT >DIGIT HOLD ; ( ud1 -- ud2 )
: #S BEGIN # 2DUP OR 0= UNTIL ; ( ud1 -- ud2 )
: #> 2DROP HLD PAD OVER - ; ( ud1 -- c-addr u )
: SIGN 0< 0= ?EXIT 02D HOLD ; ( n -- ) \ add minus sign if n<0
EXTRA: \ (AN)
: DU.STRING ( du -- a n ) <# #S #> ;
: D.STRING ( dn -- a n ) TUCK DABS <# #S ROT SIGN #> ;
: RTYPE ( a n r -- ) 2DUP MIN - SPACES TYPE ;
\ : LTYPE ( a n l -- ) 2DUP MIN 2SWAP TYPE - SPACES ;
EXTRA:
: DU. ( du -- ) DU.STRING TYPE SPACE ;
: DU.R ( du r -- ) >R DU.STRING R> RTYPE ;
FORTH:
: D. ( d -- ) D.STRING TYPE SPACE ;
: U. ( u -- ) 0 DU. ;
: . ( n -- ) S>D D. ;
: D.R ( d r -- ) >R D.STRING R> RTYPE ;
: U.R ( u r -- ) >R 0 DU.STRING R> RTYPE ;
: .R ( n r -- ) >R S>D D.STRING R> RTYPE ;
: ? @ . ;
: DECIMAL 0A BASE ! ;
: HEX 10 BASE ! ;
EXTRA:
: BINARY 2 BASE ! ;
FORTH:
: SOURCE ( -- adr n ) IB #IB ; \ current input buffer
\ : /STRING ( a n i -- a+i n-i ) TUCK - >R + R> ; \ (AN)
CODE /STRING ( a n i -- a+i n-i ) \ (AN) 2004
D X TFR \ i
S 2 #) ADDD S 2 #) STD \ a+i
S ) LDD S ) STX \ n->D i->S)
S )++ SUBD \ n-i
NEXT END-CODE
\ ----- 10 -----
\ CATCH and (THROW (AN) 2004
INSIDE:
CODE CATCH( ( xt -- ? )
REG S PSHU \ SP >R
U -2 #) LEAX REG X PSHU \ RP-2 >R
NEXT END-CODE
CODE )CATCH ( -- 0 )
U 4 #) LEAU \ wis gesavede RP en SP
REG D PSHS CLRA CLRB \ goedkeuringsnul
NEXT END-CODE
FORTH:
: CATCH CATCH( EXECUTE )CATCH ;
\ (THROW always throws and does NOT test on ZERO!
INSIDE:
CODE (THROW ( x -- ) \ (AN) 2004
D X TFR \ throw#
BEGIN
U D TFR \ RP
U )++ CMPD =?
UNTIL
REG S PULU \ restore SP
X D TFR \ throw#
REG Y PULU NEXT END-CODE
FORTH:
: ABORT ( ? -- ) -1 (THROW ;
<----
INSIDE:
CODE (LOWER ( ch -- ch2 ) \ (AN)
CHAR A # CMPB U<? NO \ A...
IF CHAR Z # CMPB U>? NO \ A..Z
IF 020 # ADDB
THEN THEN NEXT END-CODE
EXTRA:
: LOWER ( a n -- ) 0 ?DO DUP C@ (LOWER OVER C! 1+ LOOP DROP ;
---->
INSIDE:
CODE (UPPER ( ch -- ch2 ) \ (AN)
CHAR a # CMPB U<? NO \ a...
IF CHAR z # CMPB U>? NO \ a..z
IF 020 # SUBB
THEN THEN NEXT END-CODE
EXTRA:
: UPPER ( a n -- ) 0 ?DO DUP C@ (UPPER OVER C! 1+ LOOP DROP ;
FORTH:
: COMPARE ( a1 n1 a2 n2 -- 0\-1\+1 )
ROT 2DUP - >R UMIN \ a1 a2 n r: n1-n2
S<> ?DUP IF RDROP }
R> DUP 0= ?EXIT
0> 2* 1+ ;
: MOVE ( a1 a2 u -- ) \ (AN) 2004
2DUP + \ a1 a2 u a2+u
2OVER \ a1 a2 u a2+u a1 a2
WITHIN IF CMOVE }
CMOVE> ;
EXTRA:
: PLACE ( src n dst -- ) \ copy to counted string
2DUP C! CHAR+ SWAP MOVE ;
\ ----- 11 -----
FORTH:
: WORD ( char -- a ) \ (AN) 2004
>R \ r: char
SOURCE >IN @ \ BUFA BUFQ POS
/STRING TUCK \ rest adr rest
R@ SKIP \ rest worda arest
OVER SWAP \ rest a a arest
R> SCAN \ rest a wordz zrest r: --
>R \ rest a wordz r: zrest
OVER - \ rest a wordz-a
2DUP WRD 2! \ Voor QUIT en voor DNUMBER? in EVAL
HERE PLACE \ rest
R> DUP 0<> + \ rest zrest* r: --
- >IN +!
HERE ;
: PARSE ( char -- a n ) \ (AN) 2004
>R \ r: char
SOURCE >IN @ \ BUFA BUFQ POS
/STRING 2DUP \ a arest a arest
R> SCAN \ a arest stringend zrest r: --
2>R R> \ a arest zrest r: stringend
DUP 0<> + - >IN +!
R> OVER - ; \ a n r: --
EXTRA:
CODE ?STACK ( -- ) \ See S0 (AN) 2004
REG D PSHS S D TFR
TSTB 0<? NO
IF REG D PULS NEXT
THEN ( sp=100..17F )
-4 # LDB ( sp=x80..xFF, x=1 underflow, x=0 overflow )
TSTA =?
IF INCB THEN SEX ( -3 for overflow? )
' (THROW TARGA JMP END-CODE
: ?BASE ( -- ) BASE @ 2 49 WITHIN ?EXIT DECIMAL -3E (THROW ;
: ?PAIR ( x y -- ) = ?EXIT -16 (THROW ;
: ?COMP ( -- ) STATE @ ?EXIT -0E (THROW ;
FORTH:
: COMPILE, ( xt -- ) ?COMP HERE ! CELL +TO HERE ;
INSIDE:
: COMPILE() ( -- ) INLINE# COMPILE, ;
FORTH:
: [ ( -- ) FALSE STATE ! ; IMMEDIATE
: ] ( -- ) TRUE STATE ! ;
\ FLYER for state smart words (AN) 2004
INSIDE:
: SAFE-THERE ( -- a ) \ Reset THERE when not in Flybuf..+40
40 THERE FLYBUF - U<
IF FLYBUF TO THERE
THEN THERE ;
: FLYER ( -- ) \ R: caller -- THERE rest-van-FLY Caller
STATE @ ?EXIT
SAFE-THERE
HERE TO THERE
DUP TO HERE
R> 2>R \ Adres van tijdelijke code
] DIVE \ Maak nu de Caller af en keer terug naar hier.
POSTPONE EXIT \ Plak EXIT achter de tijdelijke code.
POSTPONE [
HERE THERE TO HERE TO THERE \ Herstel HERE
; \ Spring nu naar de tijdelijke code.
<----
INSIDE:
CODE "(S) ( -- a n )
REG D PSHS
Y )+ LDB CLRA
REG Y PSHS
Y B) LDY NEXT END-CODE
---->
INSIDE:
\ : C"(S) ( -- a ) INLINE$ DROP 1- ;
: "(S) ( -- a n ) INLINE$ ;
: ."(S) ( -- ) INLINE$ TYPE ;
FORTH:
: .( ( <txt"> -- ) [CHAR] ) PARSE TYPE ; IMMEDIATE
EXTRA:
: WORD, ( ch -- ) WORD C@ 1+ ALLOT ;
: PARSE, ( ch -- ) PARSE HERE OVER 1+ ALLOT PLACE ;
INSIDE:
: ABORT"(S) ( flag -- ) \ (AN) 2004
IF R@ TO MSG#-2 -2 (THROW
THEN /INLINE$ ;
\ --- R'DAM & A'DAM
FORTH:
: ABORT" ( <txt"> -- ) FLYER POSTPONE ABORT"(S)
HERE-IS ROTTERDAM
[CHAR] " PARSE, ; IMMEDIATE
EXTRA:
: " ( <txt"> -- a n |-- )
HERE-IS AMSTERDAM
FLYER POSTPONE "(S)
[ ROTTERDAM 22 ] AGAIN (;) IMMEDIATE
FORTH:
: S" ( <txt"> -- a n |-- ) [ AMSTERDAM 22 ] AGAIN (;) IMMEDIATE
: ." ( <txt"> -- ) FLYER POSTPONE ."(S) [ ROTTERDAM 22 ] AGAIN (;) IMMEDIATE
\ : C" ( <txt"> -- ) FLYER POSTPONE C"(S) [ ROTTERDAM 22 ] AGAIN (;) IMMEDIATE
EXTRA:
: MSG" ( n <ccc"> -- )
HERE SWAP , TOPMSG , TO TOPMSG
[ ROTTERDAM 22 ] AGAIN (;)
\ ---
FORTH:
: DEPTH ( -- n ) SP@ S0 SWAP - 2/ ;
\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\ ----------------- assembler hulpwoordjes --------------------
INSIDE:
: 8BIT? -80 80 WITHIN ;
: INITMODE ( -- ) \ Default value before starting an instruction
30 TO MODE ; \ zie ?ILLEGAL & Doers
: ?ILLEGAL ( flag -- ) 0= ?EXIT -3F (THROW ;
: INDEXREG ( regnr postbyte1 -- postbyte2 ) \ zie DO)MODE #)
20 TO MODE
SWAP 1- 3 OVER U< ?ILLEGAL \ must be x,y,u, or s (0..3)
5 LSHIFT OR ; \ put reg # in postbyte
<----
, A B D X Y U S
0 2 4 6 10 20 40 40
---->
: REGCODE ( ch -- regcode) \ zie REG
[CHAR] Z OVER < BL AND - >R \ UPPER
S" ,ABDXYUS87654321"
[ -8 ALLOT 2 , 406 , 1020 , 4040 , ]
2/ TUCK R> \ 8 List 8 Ch
SCAN IF + C@ }
-3F (THROW (;)
: +MODE ( operand1 -- operand2 ) \ change 5x to 0x
MODE + DUP 0F0 AND 50 <> ?EXIT 0F AND ;
: PCREL ( operand postbyte -- ) \ PC relative zie INDEXED
SWAP HERE 2 + - DUP 8BIT? \ Relative offset 8 bit?
IF SWAP 0FE AND C, C, } \ Postbyte + offset8
1- SWAP C, , ; \ Postbyte + offset16
: COFSET ( operand postbyte -- ) \ Constant offset zie INDEXED
OVER 0= IF 0F0 AND 4 OR C, DROP } \ no offset
OVER -10 10 WITHIN OVER 10 AND 0= \ 5bit and no indirection?
AND IF 60 AND SWAP 1F AND OR C, } \ 5 bit offset
OVER 8BIT? IF 0FE AND C, C, } \ 8 bit offset
C, , ; \ 16 bit offset
: INDEXED ( operand? postbyte -- )
DUP 8F AND \ check postbyte for modes with operands
DUP 89 = IF DROP COFSET } \ Constant offset
DUP 8D = IF DROP PCREL } \ PC relative
DUP 8F = IF DROP C, , } \ Extended indirect
DROP C, ; \ Simple modes: postbyte only
: IMMED ( operand opcode-pfa+ -- )
C@ 1- S>D ?ILLEGAL \ 0
IF , } \ 2
C, ; \ 1
\ ==================== de DOERS (AN) =====================
\ Inherent instructions
INSIDE:
DOER: DOSEX C@ C, INITMODE ; \ Lay 1 byte
DOER: DOSWI2 @ , INITMODE ; \ Lay cell
DOER: DOCWAI ( operand -- ) \ 8 bit, Immediate instructions
MODE ?ILLEGAL C@ C, C, INITMODE ;
<----
Stack action of general addressing instructions
(1) immediate, direct, extended: operand --
(2) all indexed except (3): postbyte --
(3) const.offset, PC, extended indir: operand postbyte --
---->
: GENADR ( adr+ -- )
MODE INITMODE
DUP 0 = IF DROP IMMED } \ Immediate
DUP 10 = IF DROP DROP C, } \ Direct
DUP 20 = IF DROP DROP INDEXED } \ Indexed
DUP 30 = IF DROP DROP , } \ Extended
?ILLEGAL ;
DOER: DONEG \ 2x 8 bit in body, General address instructions
COUNT +MODE C, GENADR ;
DOER: DOLDY \ 16 & 8 bit in body, General address instructions
@+ +MODE , GENADR ;
DOER: DOEXG \ 8 bit in body, R to R instructions
C@ C, SWAP 4 LSHIFT ( 10 * ) + C, INITMODE ;
DOER: DOLEA \ 8 bit in body, Lea instructions
MODE 20 - ?ILLEGAL
C@ C, INDEXED INITMODE ;
DOER: DOBEQ \ 8 bit in body, Conditional branches
C@ SWAP HERE 2 + - \ Distance
INITMODE
DUP 8BIT?
IF SWAP C, C, } \ 8 bit
10 C, SWAP C, 2 - , ; \ 16 bit
DOER: DOBRA \ 16 bit in body, Unconditional branches
@ SWAP HERE 2 + - \ distance
INITMODE
DUP 8BIT? IF SWAP BYTESWAP C, C, } \ 8 bit: use short opcode
SWAP C, 1- , ; \ 16 bit: use long opcode
\ DOER: DOCCON C@ ; \ 8 bit in body, Conditions, Registers
DOER: DO-) C@ INDEXREG ; \ 8 bit in body \ Modes
\ -------- De assemblerwoordjes ------
\ Zet geen commentaren binnen in een lijst!
ASSEMBLER:
NEG:
0 40 NEG 0 43 COM
0 44 LSR 0 46 ROR 0 47 ASR
0 48 ASL
0 48 LSL 0 49 ROL 0 4A DEC
0 4C INC 0 4D TST 0 4E JMP 0 4F CLR
1 80 SUBA 1 81 CMPA 1 82 SBCA 2 83 SUBD
1 84 ANDA 1 85 BITA 1 86 LDA 0 87 STA
1 88 EORA 1 89 ADCA 1 8A ORA 1 8B ADDA
2 8C CMPX 0 8D JSR 2 8E LDX 0 8F STX
1 0C0 SUBB 1 0C1 CMPB 1 0C2 SBCB 2 0C3 ADDD
1 0C4 ANDB 1 0C5 BITB 1 0C6 LDB 0 0C7 STB
1 0C8 EORB 1 0C9 ADCB 1 0CA ORB 1 0CB ADDB
2 0CC LDD 0 0CD STD 2 0CE LDU 0 0CF STU -1
LDY:
2 1083 CMPD 2 108C CMPY 2 108E LDY 0 108F STY
2 10CE LDS 0 10CF STS
2 1183 CMPU 2 118C CMPS -1
LEA: 30 LEAX 31 LEAY 32 LEAS 33 LEAU -1
EXG: 1E EXG 1F TFR -1
SEX:
12 NOP 13 SYNC 19 DAA 1D SEX
39 RTS 3A ABX 3B RTI 3D MUL 3F SWI
40 NEGA 43 COMA
44 LSRA 46 RORA 47 ASRA
48 ASLA
48 LSLA 49 ROLA 4A DECA
4C INCA 4D TSTA 4F CLRA
50 NEGB 53 COMB
54 LSRB 56 RORB 57 ASRB
58 ASLB
58 LSLB 59 ROLB 5A DECB
5C INCB 5D TSTB 5F CLRB -1
SWI2: 103F SWI2 113F SWI3 -1
CWAI: 1A ORCC 1C ANDCC
34 PSHS 35 PULS 36 PSHU 37 PULU 3C CWAI -1
BRA: 2016 BRA 8D17 BSR -1
BEQ: 21 BRN 22 BHI 23 BLS
24 BHS 25 BLO
24 BCC 25 BCS 26 BNE 27 BEQ
28 BVC 29 BVS 2A BPL 2B BMI
2C BGE 2D BLT 2E BGT 2F BLE -1
<----
\ 6809 conditions (Constanten)
CON:
20 NVR 21 ALW 22 LS 23 HI
24 LO 25 HS
24 CS 25 CC 26 EQ 27 NE
28 VS 29 VC 2A MI 2B PL
2C LT 2D GE 2E LE 2F GT -1
---->
\ 6809 conditions, (AN):
\ Forth-achtige 6809 assembler condities.
\ Deze woordjes dekken ALLE condities.
CON: 23 U>?
24 U<? 24 CS?
26 =?
28 VS? 2A 0<?
2C <? 2F >? -1
: NO ( cond# -- cond#2 ) 1 XOR ;
\ 6809 registers (Constanten)
CON:
0 D 1 X 2 Y 3 U
4 S 5 PC 8 A 9 B
0A CCR 0B DP -1
\ 6809 addressing modes
-):
80 )+ 81 )++ 82 -) 83 --)
84 ) 85 B) 86 A) 8B D) -1
\ ================ EINDE ASSEMBLER DEEL I ==================
INSIDE:
: PARENTHESIZE ( -- ) ." (" DIVE ." ) " ;
FORTH:
: .S ( -- )
?STACK PARENTHESIZE SPACE
DEPTH 0= ?EXIT
DEPTH BEGIN DUP PICK . 1-
DUP 0= UNTIL DROP ;
EXTRA:
: U.S ( -- ) \ Unsigned version of .S
?STACK PARENTHESIZE SPACE
DEPTH 0= ?EXIT
DEPTH BEGIN DUP PICK U. 1-
DUP 0= UNTIL DROP ;
EXTRA:
: .MSG ( n -- ) \ msg-body: msg# | link | text..
-3 OVER U< IF 1+ 0= ?EXIT \ msg#=-1
SPACE MSG#-2 COUNT TYPE } \ msg#=-2
TOPMSG
AHEAD
BEGIN CELL+ @ \ n 'msg
/THEN DUP @ \ n 'msg msg#
WHILE 2DUP @ =
UNTIL
THEN \ n 'msg
CELL+ CELL+ COUNT TYPE
?DUP 0= ?EXIT
PARENTHESIZE ." Message # " 0 .R ;
INSIDE:
: .OK ( -- ) \ (AN) 2005
?BASE ?STACK
OK 1 AND IF STATE @ IF ." ok"
ELSE ." OK"
THEN
THEN
CR
OK 2 AND IF .S
ELSE OK 4 AND IF U.S THEN
THEN
OK 8 AND 0= ?EXIT
0A BASE @ = ?EXIT
BASE @ DUP DECIMAL 0 .R BASE ! ." ) " ;
\ ----- 12 -----
\ Inputstream
FORTH:
: QUERY ( -- a n )
TIB DUP TO IB TIBSIZE ACCEPT TO #IB
0 >IN ! SPACE ;
FORTH:
: REFILL ( -- t/f ) TIB IB = IF .OK QUERY TRUE } FALSE ;
EXTRA:
: WORD> ( ch -- a ) \ a is never a nullstring (AN) 2004
BEGIN DUP WORD DUP C@ IF NIP }
DROP >R REFILL 0= IF -10 (THROW THEN
R>
AGAIN (;)
INSIDE:
CODE THREAD ( blword -- draadadres ) \ Len 2* Z xor 2* A xor
D X TFR \ Counted stringadres
X ) LDA A B TFR \ count
ASLB X A) EORB \ laatste karakter erbij
ASLB X 1 #) EORB \ eerste karakter erbij
HX 0F # ANDB ASLB \ offset in dradenlijst
3 # ADDB SEX \ dictionary adres = 0003
NEXT END-CODE
: FINDNAME ( blword -- nfa? ) \ nfa? is a valid nfa or zero. (AN) 2004
DUP C@ 1+ 20 MIN \ blword len+1
2DUP UPPER
OVER THREAD \ blword len+1 lfa
AHEAD
BEGIN NAME>LINK \ blword len+1 lfa
/THEN @ DUP \ blword len+1 nfa/0
WHILE DUP 2OVER S<> 0= \ blword len+1 nfa found?
UNTIL
THEN \ blword len+1 nfa/0
NIP NIP ;
: FINDWORD ( blword nfa? widstring widcount -- xt imm | blword 0 )
2>R \ a nfa r: widstring widcount
DUP
IF FALSE SWAP \ a 0 nfa
AHEAD
BEGIN NAME>LINK
CELL- @ \ a NFA? nfa*
/THEN 2R@ 2OVER NIP @VOC \ a 0 nfa widstring widcount wid
SCAN NIP \ a 0 nfa rest
R> OVER - >R
IF NIP DUP \ a NFA* nfa ( this one is OK )
THEN
DUP HOM? R@ AND \ a NFA? nfa meer?
0= UNTIL
DROP \ a NFA?
DUP IF NIP \ NFA
DUP NAME> \ NFA xt
SWAP @IMM \ xt imm
THEN \ xt imm | blword 0
THEN 2RDROP ;
FORTH:
: FIND ( blword -- xt imm ) \ (an) 2004
( blword -- blword 0 )
DUP FINDNAME \ blword nfa?
DUP 0= ?EXIT
CONTEXT CURRENT OVER - \ blword nfa? widstring widcount
FINDWORD ; \ xt imm | blword 0
: SEARCH-WORDLIST ( a n wid -- xt imm )
( a n wid -- false )
>R HERE PLACE ( -- ) \ r: wid
HERE DUP FINDNAME \ blword nfa?
R> OVER \ blword nfa? wid
IF HERE NAME> TUCK C! 1 \ blword nfa? widstring widcount=1
FINDWORD \ xt imm | blword 0
DUP ?EXIT \ xt imm
FALSE \ blword 0 dummy
THEN DROP NIP ; \ 0
INSIDE:
: !SECTION ( -- ) HERE TO SECTION ;
: LIT, ( x -- ) \ Compile x as a literal
DUP 80 -80 WITHIN IF POSTPONE () , !SECTION }
POSTPONE (C) C, !SECTION ;
FORTH:
: LITERAL ( x -- ? ) STATE @ 0= ?EXIT LIT, ; IMMEDIATE
: 2LITERAL ( xlo xhi -- ? ? ) STATE @ 0= ?EXIT SWAP LIT, LIT, ; IMMEDIATE
EXTRA:
: >OK ( x -- ) TO OK ;
\ ----- 13 -----
EXTRA:
: DIGIT> ( char -- n true | char false ) \ (AN) 2004
>R R@ [CHAR] 0 -
9 OVER U<
IF 10 OVER U<
WHILE 7 -
THEN DUP BASE @ U< IF TRUE RDROP } \ tot de 9 en vanaf de A
THEN DROP R> FALSE ; \ het ongeldige stukje tussen de 9 en de A
FORTH:
: >NUMBER ( dx adr u -- dx2 adr2 u2 )
DUP 0= ?EXIT
OVER C@ DIGIT>
IF >R 2SWAP BASE @ DU*
R> M+ 2SWAP 1 /STRING
RE
THEN DROP ;
INSIDE:
: MINUS-SIGN? ( a n -- a n false | a+1 n-1 true ) \ Behandel een eventueel minteken.
DUP
IF OVER C@ [CHAR] - = IF 1 /STRING TRUE }
THEN FALSE ;
: >DOTNUMBER ( a n -- xlo xhi a2 q )
\ q= -1 : empty string or only dot.
\ q= 0 : ok, string is converted.
\ q= +x : wrong character in the string.
FALSE DUP 2SWAP \ 0 0 a n
1- DUP 0= \ length=1?
IF OVER C@ [CHAR] . = OR \ do not accept "only dot"
THEN S>D ?EXIT \ empty string or only dot, q=-1
1+ >NUMBER
DUP TO DOT? DUP 0= ?EXIT \ ok (no dot)
OVER C@ [CHAR] . <> ?EXIT \ wrong character
DUP TO DOT? 1 /STRING >NUMBER ;
EXTRA:
: DNUMBER? ( a n -- xlo xhi true |-- ? ? false ) \ (AN) 2004
MINUS-SIGN? >R
>DOTNUMBER NIP \ xlo xhi q
IF FALSE RDROP } \ ? ? false
R> ?DNEGATE TRUE ; \ xlo xhi true
INSIDE:
: EVAL ( BLWORD -- ) \ (AN) 2004
FIND ?DUP IF STATE @ AND 0< IF , } EXECUTE }
DROP WRD 2@
DNUMBER? IF DOT? IF POSTPONE 2LITERAL } DROP POSTPONE LITERAL }
-3D (THROW (;)
: OK-LOOP ( -- )
S0 R0 CELL- CELL- ! \ When entering QUIT with numbers on stack.
BEGIN BL WORD> EVAL AGAIN (;)
FORTH:
: QUIT ( -- )
CLEAR-R
BEGIN
POSTPONE [ QUERY
['] OK-LOOP CATCH
CR INITMODE
DUP INVERT 0= IF WRD 2@ TYPE SPACE THEN ( -1? )
.MSG SPACE CLEAR-S
AGAIN (;)
CODE THROW ( x -- ) \ (AN) 2004
0 # CMPD =? IF REG D PULS NEXT THEN
-38 # CMPD =? IF REG D PULS ' QUIT TARGA JMP THEN
' (THROW TARGA JMP
END-CODE
INSIDE:
: INTERPRET ( a n -- ) \ For EVALUATE -- (AN) 2004
TO #IB TO IB 0 >IN !
AHEAD
BEGIN EVAL
/THEN BL WORD DUP C@ 0=
UNTIL DROP ;
FORTH:
: EVALUATE ( a n -- )
SOURCE 2>R >IN @ >R
['] INTERPRET CATCH
R> >IN ! 2R> TO #IB TO IB
THROW ;
INSIDE:
: ?FOUND ( t/f -- ) ?EXIT -0D (THROW (;)
FORTH:
: ' ( <name> -- xt | ABORT ) BL WORD> FIND ?FOUND ;
: CHAR ( <word> -- ch ) BL WORD> 1+ C@ ;
: [CHAR] ( <word> -- ) CHAR POSTPONE LITERAL ; IMMEDIATE
EXTRA:
: CTRL CHAR 1F AND POSTPONE LITERAL ; IMMEDIATE
FORTH:
: ( ( <tekst> -- ) [CHAR] ) PARSE 2DROP
>IN @ #IB U< ?EXIT
>IN @ IF SOURCE + 1- C@ [CHAR] ) = ?EXIT THEN
REFILL ?RE ; IMMEDIATE
: \ ( <tekst> -- ) #IB >IN ! ; IMMEDIATE
\ ----- 14 -----
\ ---
FORTH:
: CREATE ( <name> -- ) \ (AN) 2004
BL WORD>
HERE-IS AMSTERDAM
FINDNAME DUP
>R
HERE 3 R@ IF CELL+ THEN ALLOT
DUP HERE OVER C@ 1+ CMOVE>
! \ eventually !homlink
0 \ homvocimm byte
R> IF CR ." Redefining "
HERE COUNT TYPE SPACE
80 OR \ homvocimm byte
THEN
HERE 1- C! \ !homvocimm
HERE DUP THREAD \ a th
DUP @ HERE NAME>LINK ! \ !link ---
HERE SWAP ! \ new top of the thread
HERE 1-
CURRENT C@ OVER C@ OR SWAP C! \ !voc ---
HERE TO TOPNFA \ new topnfa
C@ 1+ ALLOT \ allot name field
FALSE JSR \ allot code field
DOCREATE !SECTION ;
INSIDE:
: CREA ( stradr len -- ) HERE PLACE HERE [ AMSTERDAM 22 ] AGAIN (;)
\ ---
FORTH:
: RECURSE ( -- ) TOPNFA NAME> COMPILE, ; IMMEDIATE
EXTRA:
: HIDE TOPNFA DUP C@ 80 OR SWAP C! ;
: REVEAL TOPNFA DUP C@ 7F AND SWAP C! ;
FORTH:
: IMMEDIATE TOPNFA 1- 1 OVER C@ OR SWAP C! ;
: ['] ( <name> -- ) ' POSTPONE LITERAL ; IMMEDIATE
: [COMPILE] ( <name> -- ) ' COMPILE, ; IMMEDIATE
: POSTPONE ( <name> -- ) \ POSTPONE the action following word
BL WORD> FIND DUP ?FOUND
0< IF COMPILE() COMPILE() !SECTION CELL +TO SECTION THEN \ non-immediate
COMPILE, ; IMMEDIATE
<----
: ENVIRONMENT? \ c-addr u -- i*x true system query
2DROP 0 ; \ -- false
---->
EXTRA:
: STOP? ( - true/false )
KEY? DUP 0= ?EXIT
DROP KEY
BL OVER = IF DROP KEY THEN
1B OVER = -1C AND THROW
BL <> ;
\ ----- 15 -----
FORTH:
: : ( <name> -- )
CREATE DO: ] HIDE
TRUE FALSE >CS ;
: :NONAME
HERE
['] DO: >BODY JSR
]
FALSE FALSE >CS
!SECTION ;
: CONSTANT ( x <name> -- )
CREATE DUP 80 -80 WITHIN IF DOCON , }
DOCCON C, ;
: VARIABLE ( <name -- ) CREATE DOVAR CELL ALLOT ;
: VALUE ( x <name> -- ) CREATE DOVAL , ;
INSIDE:
DOER: DOSTRING 1+ COUNT ;
EXTRA:
: STRING ( n <name> -- )
CREATE DOSTRING FF AND 1 MAX DUP C, FALSE C, ALLOT ;
INSIDE:
: TO$() ( a n inl-body -- )
INLINE# DUP 1+ >R
C@ UMIN
R> PLACE ;
: +TO$() ( a n inl-body -- )
INLINE# DUP 1+ >R
C@ R@ C@ - UMIN
R@ COUNT + SWAP
DUP R> C+!
MOVE ;
: INCR$() ( ch <name> -- )
INLINE# DUP 1+ >R
C@ R@ C@
> IF R@ COUNT + C! 1 R> C+! }
DROP RDROP ;
PFXLIST ] DOSTRING TO$() +TO$() INCR$() [
PFXLIST ] DOVAL TO() +TO() INCR() [
: PFXLIST TOPPFX , HERE TO TOPPFX ;
: PFX ( offset-in-pfxlist <name> -- ) \ (AN) 2004
' >BODY
DUP CELL- @ BODY> \ n data-body doer-xt
TOPPFX \ n data-body doer-xt pfx-list
BEGIN 2DUP @ = \ juiste type?
IF NIP CELL+ ROT + @ \ data-body pfx-actie
FLYER
\ DUP >NAME @IMM 0< IF EXECUTE }
, , }
CELL- @ DUP 0= \ volgende pfx-list
UNTIL -20 (THROW (;)
FORTH:
: TO ( <name> -- ) 0 PFX ; IMMEDIATE
EXTRA:
: +TO ( <name> -- ) 2 PFX ; IMMEDIATE
: INCR ( <name> -- ) 4 PFX ; IMMEDIATE
EXTRA:
: VARIABLES ( n <name> -- ) CREATE CELLS ALLOT DOVARS ;
\ ----- 16 -----
INSIDE:
: <FUSE ( 3-inline-tokens -- )
?COMP R>
@+ HERE CELL- @ =
SECTION HERE 1- U< AND
IF -2 ALLOT CELL+ @+ ,
ELSE @+ , CELL+
THEN >R ;
\ When xt1 is not the last compiled word: compile xt2
\ Otherwise: overwrite compiled xt1 with xt3
\ See ?EXIT IF UNTIL ?RE
EXTRA:
: ?EXIT <FUSE 0= EXIT-ON-TRUE EXIT-ON-FALSE ; IMMEDIATE
\ --- A'DAM
FORTH:
: IF ( -- sysif ) <FUSE 0= IF() IFZERO()
HERE-IS AMSTERDAM HERE DUP , 1 >CS ; IMMEDIATE
: AHEAD ( -- sysif ) POSTPONE GOTO() [ AMSTERDAM 22 ] AGAIN (;) IMMEDIATE
\ ---
FORTH:
: WHILE ( sys -- sysif sys ) POSTPONE IF 1 CS-ROLL ; IMMEDIATE
: THEN ( syfif -- ) ?COMP CS> 1 ?PAIR HERE SWAP ! !SECTION ; IMMEDIATE
: BEGIN ( -- sysbegin ) ?COMP HERE 2 >CS !SECTION ; IMMEDIATE
: UNTIL ( sysbegin -- ) CS> 2 ?PAIR <FUSE 0= IF() IFZERO() , ; IMMEDIATE
: AGAIN ( sysbegin -- ) CS> 2 ?PAIR POSTPONE GOTO() , ; IMMEDIATE
: ELSE ( sysif1 -- sysif2 ) POSTPONE AHEAD 1 CS-ROLL POSTPONE THEN ; IMMEDIATE
: REPEAT ( sysif sysbegin -- ) POSTPONE AGAIN POSTPONE THEN ; IMMEDIATE
\ --- R'DAM
FORTH:
: DO ( -- sysdo ) POSTPONE DO() HERE-IS ROTTERDAM HERE DUP , 3 >CS ; IMMEDIATE
: ?DO ( -- sysdo ) POSTPONE ?DO() [ ROTTERDAM 22 ] AGAIN (;) IMMEDIATE
\ ---
\ --- A'DAM
FORTH:
: LOOP ( sysdo -- )
CS> 3 ?PAIR POSTPONE LOOP()
HERE-IS AMSTERDAM DUP CELL+ , HERE SWAP ! ; IMMEDIATE
: +LOOP ( sysdo -- )
CS> 3 ?PAIR POSTPONE +LOOP() [ AMSTERDAM 22 ] AGAIN (;) IMMEDIATE
\ ---
: ; ( sys: -- )
CS> FALSE ?PAIR IF REVEAL THEN POSTPONE EXIT POSTPONE [ ; IMMEDIATE
EXTRA:
: } ( sysif -- ) POSTPONE EXIT POSTPONE THEN ; IMMEDIATE
\ --- A'DAM
EXTRA:
: RE ( -- ) POSTPONE GOTO() HERE-IS AMSTERDAM TOPNFA NAME> >BODY , ; IMMEDIATE
: ?RE ( -- ) <FUSE 0= IFZERO() IF() [ AMSTERDAM 22 ] AGAIN (;) IMMEDIATE
\ ---
EXTRA:
: RE} ( sysif -- ) POSTPONE RE POSTPONE THEN ; IMMEDIATE
INSIDE:
DOER: DOONLY
C@ CURRENT 1- 2DUP C!
1- DUP TO CONTEXT C! ;
DOER: DOVOC C@ CONTEXT C! ;
FORTH:
MAKEONLY ONLY \ 0
ONLY:
VOCABULARY FORTH \ 2
VOCABULARY INSIDE \ 4
VOCABULARY EXTRA \ 6
VOCABULARY ASSEMBLER \ 8
\ Search order words (an)
FORTH:
: WORDLIST ( -- v#=wid )
HERE
TOPVOC DUP C@ 2 + C, ,
DUP TO TOPVOC C@ ;
ONLY:
: ALSO ( -- )
FINDSTACK CONTEXT U< 0= -31 AND THROW
CONTEXT C@ -1 +TO CONTEXT
CONTEXT C! ;
: PREVIOUS ( -- )
CONTEXT 1+ CURRENT U< 0= -32 AND THROW
INCR CONTEXT ;
: DEFINITIONS CONTEXT C@ CURRENT C! ;
: GET-CURRENT ( -- wid ) CURRENT C@ ;
: SET-CURRENT ( wid -- ) CURRENT C! ;
INSIDE:
: VOCNAME ( wid -- a n )
TOPVOC
BEGIN 2DUP C@ =
IF NIP BODY> >NAME COUNT 1F AND
} 1+ @ DUP 0=
UNTIL 2DROP S" ?" ;
EXTRA:
: .VOC ( wid -- ) VOCNAME TYPE ;
ONLY:
: ORDER ( -- ) \ (AN) 2004
PARENTHESIZE
CONTEXT CURRENT OVER -
0 DO COUNT .VOC SPACE
LOOP ." : " C@ .VOC ;
: FRESH ONLY EXTRA ALSO FORTH ALSO ;
EXTRA:
: VOCABULARY CREATE WORDLIST DROP DOVOC ;
INSIDE:
: !TOPNFA ( -- )
FALSE 23 3
DO I @ ORIGIN - UMAX
CELL +LOOP ORIGIN + TO TOPNFA ;
: CURTAIL ( fence here linkfield distance -- fence here linkfield2 )
>R
AHEAD
BEGIN
R@ + \ object-adr + distance = linkfield-adr
@
/THEN
DUP 2OVER WITHIN 0=
UNTIL RDROP ;
: (FORGET ( fence -- )
HERE 23 3
DO I @ -3 CURTAIL I !
CELL
+LOOP
TOPVOC 1 CURTAIL TO TOPVOC
TOPMSG 2 CURTAIL TO TOPMSG
TOPPFX -2 CURTAIL TO TOPPFX
- ALLOT !TOPNFA ;
\ --- A'DAM
FORTH:
: FORGET ( <name> -- )
BL WORD> COUNT CURRENT C@ SEARCH-WORDLIST ?FOUND
>NAME \ NFA
HERE-IS AMSTERDAM
DUP NAME>LINK SWAP HOM? 2 AND - \ fence
HERE OVER U< -0F AND THROW (FORGET ; \ OK for RAM and ROM version
EXTRA:
: REMOVE ( -- ) \ Remove last word when hidden (AN) 2004
TOPNFA C@ 80 AND 0= ?EXIT
REVEAL TOPNFA DUP COUNT TYPE SPACE \ NFA
[ AMSTERDAM 22 ] AGAIN (;) \ See FORGET
\ ---
INSIDE:
DOER: DOMARKER
DUP @ (FORGET \ vergeet vanaf oldhere
CELL+ COUNT DUP TO CONTEXT \ herstel CONTEXT = adres < 100
CURRENT OVER - 1+ MOVE ; \ herstel zoekstack-vocs
FORTH:
: MARKER ( <name> -- ) \ (AN) 2004
HERE CREATE DOMARKER
, \ oldhere
CONTEXT DUP C, \ save CONTEXT = adres < 100
HERE CURRENT CONTEXT - 1+
DUP ALLOT MOVE ; \ save zoekstack-vocs
EXTRA:
: ANEW ( <name> -- ) \ (AN) 2004
>IN @ >R
BL WORD DUP C@ 0= -20 AND THROW \ no refill because of saving >IN
FIND 0<> AND ?DUP
IF DUP 1+ @ BODY>
['] DOMARKER = AND ?DUP IF EXECUTE THEN
THEN R> >IN ! MARKER ;
\ ----- 17 -----
INSIDE:
: !HIMEM ( -- ) \ test eerste cell per 2K RAM (AN) 2004
-800 TO HIMEM
BEGIN 800 +TO HIMEM
HIMEM @ ( x ) \ lees
DUP INVERT HIMEM ! ( x ) \ store geinverteerde x
HIMEM @ ( x xi? ) \ lees het terug
OVER HIMEM ! ( x xi? ) \ zet correcte x terug
INVERT <> ( vlag ) \ ongelijk?
UNTIL ; \ laagste niet bestaande RAM adres staat nu in HIMEM
FORTH:
: UNUSED ( -- n ) HIMEM 20 - HERE - ;
EXTRA:
CODE COLD ( ? -- ) \ cold start Forth system (AN) 2004
CLRA A DP TFR \ initial DP, direct page
' S0 >BODY @ # LDS \ initial SP
REG D PULS
' R0 >BODY @ # LDU \ initial RP
' DO: 3 + TARGA JSR \ Overgang naar hilevel code
END-CODE
]
ORIGIN 0 [ UOFFSET ] LITERAL CMOVE
!HIMEM !TOPNFA 0 TO CS#
SAFE-THERE DROP
FRESH DEFINITIONS
7F !USART
CR 0 .MSG
CR ." Copyright (c) 2005 HCC Forth-gg"
CR HIMEM 0A RSHIFT 9 .R ." kB RAM"
CR CR QUIT [
INSIDE:
: (DOES> ( -- ) R> !DOER ; \ TOPNFA NAME> 1+ ! ;
FORTH:
: DOES>
CS> FALSE OVER ?PAIR >CS
POSTPONE (DOES>
['] DODOES JSR
!SECTION ; IMMEDIATE
: CODE ( <name> -- ) CREATE -3 ALLOT ASSEMBLER HIDE TRUE 5 >CS ;
: ;CODE
CS> FALSE ?PAIR 5 >CS
POSTPONE (DOES>
ASSEMBLER
POSTPONE [ ; IMMEDIATE
EXTRA:
: DOER: ( <name> -- ) : DODOER ['] DODOES JSR ;
: DOERCODE ( <name> -- ) CODE 3 ALLOT DODOER ;
ASSEMBLER:
: END-CODE
CS> 5 ?PAIR IF REVEAL THEN
PREVIOUS ALSO ;
<----
INSIDE:
DOER: DOIGNORE ( a -- )
DUP C@ 1+ 2>R
BEGIN BL WORD> 2R@ S<> 0=
UNTIL 2RDROP ;
EXTRA:
: IGNORE ( <name> <name> -- ) \ Skipper and delimiter, (AN) 2004
CREATE BL WORD> C@ 1+ ALLOT DOIGNORE IMMEDIATE ;
\ Voorbeeld:
\ IGNORE <<< >>> \ FORTH will now skip text between <<< and >>>
\ IGNORE AAA ZZZ \ ZZZ is Case sensitive!
---->
\ Interrupt vectoren
EXTRA:
: !VECTOR ( routineadres vec -- ) 1+ ! ; \ vb: C4A5 'SWI3 !VECTOR
: ENABLE ( vec -- ) 07E SWAP C! ; \ ( JMP ) 'SWI3 ENABLE
: DISABLE ( vec -- ) 03B SWAP C! ; \ ( RTI ) 'SWI3 DISABLE
EXTRA:
: MANY ( -- ) >IN @ STOP? AND >IN ! ;
: TIMES ( n -- )
#TIMES 1+ >R
0 TO #TIMES
R@ = \ Last time?
STOP? \ User interrupt?
OR IF RDROP } \ No repeat
R> TO #TIMES \ Repeat
0 >IN ! ;
\ ----- 18 -----
<----
: /WORDS \ Per draad (an) 2004
3 10 0
DO CR I . \ .DRAADNR
DUP @ 0 >R
BEGIN DUP COUNT 7F AND
DUP HOR + 4E > IF CR ELSE SPACE THEN
TYPE
R> 1+ >R
NAME>LINK @
DUP 0= UNTIL DROP ." -- " R> .
2 +
NOMORE? IF LEAVE THEN
LOOP DROP ;
---->
\ (AN) 2004 -- WORDS
INSIDE:
: WORDSKIPPER ( lfa wid -- nfa? )
SWAP \ wid lfa
AHEAD
BEGIN NAME>LINK \ wid lfa
/THEN @ \ wid nfa/0
DUP
WHILE 2DUP @VOC = \ wid nfa flag
UNTIL
THEN \ wid nfa/0
NIP ;
: (WORDS ( x y -- ) \ (AN) 2004
SAFE-THERE 2!
THERE 24 + DUP 20 - \ T24 T4
3 OVER 20 CMOVE \ Store the threads at THERE+4
2DUP \ T24 T4 T24 T4
DO I THERE 2@ EXECUTE I ! \ Skipper
CELL
+LOOP
CR 0 >R \ Woordenteller
BEGIN \ T24 T4
FALSE -1 \ Voor Relatieve-NFA en Draadadres
2OVER
DO I @ \ NFA?
IF OVER I @ ORIGIN - U< \ Hoogste?
IF 2DROP I @ ORIGIN - I \ RelatiEve-NFA Draada
THEN
THEN CELL
+LOOP \ Grootste-relatieve-NFA Draadadres | 0 -1
NIP \ T24 T4 Draadadres-or-True
S>D STOP? \ Klaar of Stoppen?
OR IF DROP 2DROP CR R> PARENTHESIZE 0 .R } \ \ \ \ \ e x i t
3C HOR U< IF CR THEN \ Positie op de regel
R> 1+ >R \ Woordenteller
DUP @ \ Draada NFA
DUP COUNT \ Draada NFA a n
DUP 20 < IF BL
ELSE 1F AND [CHAR] ~
THEN EMIT TYPE SPACE
NAME>LINK \ Draada Lfa
THERE 2@ EXECUTE \ Draada Next-NFA
SWAP !
AGAIN (;)
ONLY:
: WORDS CONTEXT C@ ['] WORDSKIPPER (WORDS ;
EXTRA:
: ALLWORDS ['] @ ['] EXECUTE (WORDS ;
\ : DWORDS CURRENT C@ ['] WORDSKIPPER (WORDS ;
INSIDE:
: X.R! ( -- n ) FF S>D DU.STRING NIP THERE C! ; \ Zie .ADR .ASC
: .ADR ( a -- ) THERE C@ 2* U.R ;
: .BYTE ( c -- ) THERE C@ .R ;
: .ASC ( ch -- ) DUP 7F < AND BL MAX EMIT ;
\ DUMP voor alle grondtallen, met noodstop.
FORTH:
: DUMP ( a n -- ) \ (AN) 2004
X.R! \ Zie .ADR
BASE @ 10 MIN DUP 6 < IF 2* THEN >R \ aantal bytes per regel
OVER + SWAP \ tot vanaf
BEGIN DUP CR .ADR SPACE \ tot vanaf
R@ 0 DO DUP I + C@ .BYTE SPACE
LOOP ." |" \ tot vanaf
R@ 0 DO COUNT .ASC
LOOP ." | " \ tot vanaf*
2DUP SWAP - R@ U< \ einde bereikt?
STOP? OR
UNTIL 2DROP RDROP ;
\ Decompiler (AN) 2004
INSIDE:
: CFA?? ( adr -- vlag )
300 OVER U<
OVER ORIGIN HERE WITHIN AND
SWAP 1- DUP C@ 21 7F WITHIN AND AND DUP 0= ?EXIT
1 ( adr teller )
BEGIN >R 1- R> OVER C@ ( adr-1 teller char )
2DUP = IF 2DROP 0<> } \ exit with true-flag
21 7F WITHIN
WHILE 1+ BL OVER AND ( adr teller+1 x )
UNTIL
THEN 2DROP FALSE ;
: CFA? ( adr -- vlag )
DUP CFA?? AND DUP 0= ?EXIT
>NAME TOPVOC C@ OVER @VOC < 0= AND
DUP 0= ?EXIT
NAME>LINK @ DUP 0= IF 1- }
DUP C@ 0 20 WITHIN IF NAME> CFA?? }
DROP FALSE ;
: .HEAD ( a -- ) \ hier begint een header
DUP S" -- " 2>R 2R@ TYPE
>NAME COUNT TYPE
2R@ TYPE
DUP 1+ @ BODY>
DUP CFA? \ doer?
IF DUP ." doer "
>NAME COUNT TYPE
THEN
DROP 2R> TYPE
>NAME @VOC .VOC ." Word" ;
: .TOKEN ( a cfa -- a ) \ Gecompileerd token
OVER 1 AND 2* 2* 4 + SPACES
>NAME COUNT TYPE ;
: DECOM ( a -- )
CR DUP .ADR ." : "
DUP COUNT DUP .BYTE SPACE .ASC SPACE
C@ DUP .BYTE SPACE .ASC SPACE
DUP @ .ADR BL OVER 1 AND IF 0E + THEN EMIT SPACE
DUP CFA? IF DUP .HEAD 1+ }
DUP @ CFA?
IF DUP @ .TOKEN
1+
DUP CFA? ?EXIT
DUP @ CFA? ?EXIT
1+ }
1+ ;
EXTRA:
: MSEE ( a -- ) X.R! \ Used by .ADR .ASC
BEGIN DECOM STOP? UNTIL DROP ;
FORTH:
: SEE ' MSEE ;
\ ----- 19 -----
\ tijdelijke BASE (AN) 2004
INSIDE:
DOER: DOFFBASE
BASE @ >R
C@ BASE !
BL WORD>
['] EVAL CATCH
R> BASE ! THROW ;
\ In metacompiler:
\ : FFBASE ( tempbase <name> -- ) XHEADER MET-DOER DOFFBASE C, XIMMEDIATE ;
INSIDE:
: FFBASE ( tempbase <name> -- ) CREATE DOFFBASE C, IMMEDIATE ; \ (AN) 2004
ONLY:
10 FFBASE HX \ direct hexadecimal
0A FFBASE DM \ direct decimal
2 FFBASE BN \ direct binary
ONLY:
: [THEN] ; IMMEDIATE
INSIDE:
: [CONDITIONAL] ( 0 -- ) \ (AN) 07dec2005
AHEAD
BEGIN DROP
/THEN BL WORD> DUP 1+ C@ [CHAR] [ =
UNTIL \ Yes, first char = [
COUNT 1 /STRING 2DUP UPPER
2DUP S" THEN]" COMPARE 0= IF 2DROP 0= ?EXIT RE}
2DUP S" ELSE]" COMPARE 0= IF 2DROP ?DUP 0= ?EXIT RE}
2DUP S" IF]" COMPARE 0= IF 2DROP DUP 1+ RE}
S" AHEAD]" COMPARE 0= IF DUP 1+ THEN
RE (;)
ONLY:
: [ELSE] ( -- ) 0 [CONDITIONAL] ; IMMEDIATE
: [AHEAD] ( -- ) POSTPONE [ELSE] ; IMMEDIATE
: [IF] ( vlag -- ) ?EXIT POSTPONE [ELSE] ; IMMEDIATE
FORTH:
: MS ( x -- ) 0 ?DO 12 0 DO LOOP LOOP ;
\ =========== ASSEMBLER CODA ==========
\ 6809 addressing modes
ASSEMBLER:
: # 0 TO MODE ;
: REG ( "lijst" -- regbyte ) \ voorbeelden: REG D,X REG X REG X,Y
0 BL WORD
COUNT 0 ( 0=regbyte adres count )
?DO ( regbyte adres )
COUNT
REGCODE SWAP >R OR R> ( regbyte2 adres ) \ Bouw reg byte op
LOOP
DROP FLYER LIT, POSTPONE # ; IMMEDIATE
: ALLREG 0FF # ; \ voor push/pull van alle registers
: DP) 10 TO MODE ; \ DP relative
: #) SWAP 89 INDEXREG ; ( rval n -- n postbyte ) \ indexregister + offset
: PC) 20 TO MODE 8D ; ( n -- n postbyte ) \ pc relative
: []
MODE
20 = IF DUP 9D AND
80 = ?ILLEGAL
10 + } \ Indexed: postbyte -- postbyte
20 TO MODE 9F ; \ Extended: n -- n postbyte
\ 6809 structured conditionals with compiler controll
: IF ( cond# -- cs: ifadr 6 ) C, 0 C, HERE 6 >CS ;
: AHEAD ( -- cs: aheadadr 6 ) 20 ( NVR ) IF ;
: THEN ( cs: adr 6 -- )
CS> 6 ?PAIR HERE OVER -
DUP 8BIT? 0= ?ILLEGAL SWAP 1- C! ;
: BEGIN ( c": -- beginadr 7 ) HERE 7 >CS ;
: UNTIL ( cond# cs: beginadr 7 -- ) CS> 7 ?PAIR SWAP C, HERE 1+ -
DUP 8BIT? 0= ?ILLEGAL C, ;
: AGAIN ( cs: beginadr 7 -- ) 20 ( NVR ) UNTIL ;
: ELSE ( cs: ifadr 6 -- elseadr 6 ) AHEAD 1 CS-ROLL THEN ;
: REPEAT ( cs: whileadr 6 beginadr 7 -- ) AGAIN THEN ;
: WHILE ( cond# cs: adr n -- whileadr 6 adr n ) IF 1 CS-ROLL ;
: NEXT Y )++ [] JMP ; \ 6809 Direct Threaded Code
\ ----- 20 -----
\ THROW messages
FORTH:
0 MSG" MaisForth an601" \ Default message
' TOPMSG 3 + @ ORIGINHOSTA + @ 4 +
' MSG#-2 3 + @ ORIGINHOSTA + ! \ Default pointer in msg#-2
-3 MSG" Stack overflow"
-4 MSG" Stack underflow"
( -13 ) -0D MSG" Can't find"
( -14 ) -0E MSG" Only compiling"
( -15 ) -0F MSG" Protected"
( -16 ) -10 MSG" End of input"
( -22 ) -16 MSG" Structure error"
( -28 ) -1C MSG" User interrupt"
( -32 ) -20 MSG" Invalid name argument"
( -49 ) -31 MSG" Search order overflow"
( -50 ) -32 MSG" Search order underflow"
( -61 ) -3D MSG" What's this?"
( -62 ) -3E MSG" BASE is reset to decimal"
( -63 ) -3F MSG" Illegal addressing mode"
\ ( -64 ) -40 MSG" Ivalid Baud rate"
\ store starting adres on last memory address - 2
' COLD ORIGINHOSTA -2 + COMPILE! \ Resetvector vullen
' COLD ORIGINHOSTA 1 + COMPILE! \ Jump naar COLD (op ORIGIN)
;;;MAIS;;;
<---- ANS:
Throw# Reserved for
--- ---
-1 ABORT
-2 ABORT"
-3 stack overflow
-4 stack underflow
-5 return stack overflow
-6 return stack underflow
-7 do-loops nested too deeply during execution
-8 dictionary overflow
-9 invalid memory address
-10 division by zero
-11 result out of range
-12 argument type mismatch
-13 undefined word
-14 interpreting a compile-only word
-15 invalid FORGET
-16 attempt to use zero-length string as a name
-17 pictured numeric output string overflow
-18 parsed string overflow
-19 definition name too long
-20 write to a read-only location
-21 unsupported operation (e.g., AT-XY on a too-dumb terminal)
-22 control structure mismatch
-23 address alignment exception
-24 invalid numeric argument
-25 return stack imbalance
-26 loop parameters unavailable
-27 invalid recursion
-28 user interrupt
-29 compiler nesting
-30 obsolescent feature
-31 >BODY used on non-CREATEd definition
-32 invalid name argument (e.g., TO xxx)
-33 block read exception
-34 block write exception
-35 invalid block number
-36 invalid file position
-37 file I/O exception
-38 non-existent file
-39 unexpected end of file
-40 invalid BASE for floating point conversion
-41 loss of precision
-42 floating-point divide by zero
-43 floating-point result out of range
-44 floating-point stack overflow
-45 floating-point stack underflow
-46 floating-point invalid argument
-47 compilation word list deleted
-48 invalid POSTPONE
-49 search-order overflow
-50 search-order underflow
-51 compilation word list changed
-52 control-flow stack overflow
-53 exception stack overflow
-54 floating-point underflow
-55 floating-point unidentified fault
-56 QUIT
-57 exception in sending or receiving a character
-58 [IF], [ELSE], or [THEN] exception
---->