Tali Forth for the 65c02
Re: Introducing Tali Forth for the 65c02 (ALPHA)
I had copied and pasted the word into Gforth, which did just fine, so it's definitely some problem with Tali somewhere. I'm wondering if the gods of computing are trying to tell me that I should finally switch from 0BRANCH/BRANCH to CS-ROLL/CS-PICK ...
(The space after twenty just makes sure the string doesn't run into the next number, though it does look weird. The balance is okay because of the DUP -- IF always eats one I and . (that's DOT) always prints the other.)
I'm assuming there is one stupid one-byte-off mistake somewhere. Will try to see this evening if Tali 1 has the same problem first, which would make it more fundamental.
(The space after twenty just makes sure the string doesn't run into the next number, though it does look weird. The balance is okay because of the DUP -- IF always eats one I and . (that's DOT) always prints the other.)
I'm assuming there is one stupid one-byte-off mistake somewhere. Will try to see this evening if Tali 1 has the same problem first, which would make it more fundamental.
- barrym95838
- Posts: 2056
- Joined: 30 Jun 2013
- Location: Sacramento, CA, USA
Re: Introducing Tali Forth for the 65c02 (ALPHA)
scotws wrote:
... The balance is okay because of the DUP -- IF always eats one I and . (that's DOT) always prints the other.)
Mike B.
P.S. Where is your control stack, BTW? I haven't dug deeply enough to know yet. A.3.2.3 does a very thorough job of explaining what you should be doing, but it's at the limit of my abilities to fully grok.
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Introducing Tali Forth for the 65c02 (ALPHA)
There's no ELSE or UNLOOP or EXIT or LEAVE or anything that wold keep . from getting executed.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Introducing Tali Forth for the 65c02 (ALPHA)
Well, the inside of the loop looks sort of like this: The whole IF/THEN construct doesn't touch the stack, so the number gets passed on; the ." twenty " just prints "twenty", but doesn't touch the stack (well, stuff happens in the background, but it all cancels out).
At the moment, Tali uses the old 0BRANCH and BRANCH structures from FIG Forth, and the command stack is the Return Stack, thanks to some code magic suggested by Garth. What I probably should do is implement CS-ROLL and CS-PICK using the Data Stack ... having old FIG stuff in what is supposed to be an ANSI Forth is sort of cheating
.
Code: Select all
i ( u )
dup ( u u )
20 ( u u 20 )
= ( u f )
if ." twenty " then ( u )
. ( )At the moment, Tali uses the old 0BRANCH and BRANCH structures from FIG Forth, and the command stack is the Return Stack, thanks to some code magic suggested by Garth. What I probably should do is implement CS-ROLL and CS-PICK using the Data Stack ... having old FIG stuff in what is supposed to be an ANSI Forth is sort of cheating
Re: Introducing Tali Forth for the 65c02 (ALPHA)
So, it seems that the issue was a stupid typo while copying the routine from TF1 to TF2, which was pretty clear once I found that Tali Forth 1 didn't show the same issue. Will test various incarnations to make sure it's gone, though.
- barrym95838
- Posts: 2056
- Joined: 30 Jun 2013
- Location: Sacramento, CA, USA
Re: Introducing Tali Forth for the 65c02 (ALPHA)
GARTHWILSON wrote:
There's no ELSE or UNLOOP or EXIT or LEAVE or anything that wold keep . from getting executed.
Mike B.
Re: Introducing Tali Forth for the 65c02 (ALPHA)
barrym95838 wrote:
GARTHWILSON wrote:
There's no ELSE or UNLOOP or EXIT or LEAVE or anything that wold keep . from getting executed.
This is good example of a line that should be broken into two words anyway:
Code: Select all
: .twenty ( u -- ) 20 = if ." twenty " then ;Code: Select all
: aaa ( -- ) 100 10 do i dup .twenty . loop ;(Where I still totally suck are loops, which still tend to have a rather Pythonic appearance when I write them; I know that mentally, I'm trying to build something with BREAK and CONTINUE, which Forth simply doesn't have ...)
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Introducing Tali Forth for the 65c02 (ALPHA)
Rather than factor it out and give it its own memory-consuming header and incurring the extra nest-unnest overhead, you can factor it in place whichever way it becomes most visually intuitive. Some people say a definition should be only a line or two, but then they put too much on a line and make it hard to read at a glance. A couple of the many ways you could do it are:
The DO could be put at the end of the line that sets up the loop limit and index, but if I were teaching a class, I would insist that the accompanying LOOP then be straight down from it. It drives me nuts when I have to go looking for a word's pair because it's diagonal and buried so it doesn't stand out. I suppose that's what syntax highlighting is for; but I maintain that if it's laid out correctly, syntax highlighting is not necessary (except that I do like it in html which is an entirely different ball game).
In systems where DUP is no faster than I, I would keep the stack shallower, this way:
(and again, there are several ways to do it).
With exaggerated commenting:
Add them!
That's a benefit of Forth. You can add virtually anything. What do they do in Python? There might already be an equivalent in Forth.
Code: Select all
: AAA
100 10
DO I
DUP 20 =
IF ." twenty " THEN
.
LOOP ;Code: Select all
: AAA
100 10
DO I
DUP 20 = IF
." twenty " THEN
.
LOOP ;The DO could be put at the end of the line that sets up the loop limit and index, but if I were teaching a class, I would insist that the accompanying LOOP then be straight down from it. It drives me nuts when I have to go looking for a word's pair because it's diagonal and buried so it doesn't stand out. I suppose that's what syntax highlighting is for; but I maintain that if it's laid out correctly, syntax highlighting is not necessary (except that I do like it in html which is an entirely different ball game).
In systems where DUP is no faster than I, I would keep the stack shallower, this way:
Code: Select all
: AAA
100 10
DO I 20 =
IF ." twenty " THEN
I .
LOOP ;(and again, there are several ways to do it).
With exaggerated commenting:
Code: Select all
: AAA ( -- )
100 10 \ <tell significance of the limit and index> ^ lim, index
DO I 20 = \ Is the index 20? <And what is 20?> ^ f
IF ." twenty " THEN \ If so, print/display this. ^ <empty>
I . \ Regardless, display the index value. ^ <empty>
LOOP ; \ Go back for the next one. ^ <empty>Quote:
I'm trying to build something with BREAK and CONTINUE, which Forth simply doesn't have ...)
Add them!
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Introducing Tali Forth for the 65c02 (ALPHA)
@Garth - CONTINUE skips the rest of the loop and goes to the next iteration, BREAK exits the loop. I'm sure we could figure something out, but first, I need to get this running stable
.
@Mike - I've applied the patch for branch_runtime, and it works fine, thanks! Zero_branch_runtime has different code now, and for some reason, after the first patch, SEE crashes with garbage: I have no idea what that is about, since words other than SEE seem to work, but will keep this in mind and check later, because this could very well due to a totally different bug somewhere. Thanks again!
@Mike - I've applied the patch for branch_runtime, and it works fine, thanks! Zero_branch_runtime has different code now, and for some reason, after the first patch, SEE crashes with garbage:
Code: Select all
see within
3C00 ���`��0
0
0000 ok- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Introducing Tali Forth for the 65c02 (ALPHA)
scotws wrote:
@Garth - CONTINUE skips the rest of the loop and goes to the next iteration
Code: Select all
: FOOBAR
<set up lim & index>
DO <bla bla bla>
<bla bla bla>
<condition> \ "CONTINUE" is what you get if condition false.
IF <more stuff>
<more stuff>
<more stuff>
THEN
LOOP
<more instructions> ;I wouldn't add the word CONTINUE, but it could be done, as an IMMEDIATE compile-only word, using the address left by DO during compilation.
Quote:
BREAK exits the loop.
That sounds like it's exactly the same as LEAVE in Forth. I also use ?LEAVE, a more-concise way to do IF LEAVE THEN.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
-
leepivonka
- Posts: 168
- Joined: 15 Apr 2016
Re: Introducing Tali Forth for the 65c02 (ALPHA)
Here is a Fibonacci routine that prints all the numbers as it goes:
Code: Select all
: fib ( -- )
0 1 begin dup . swap over + dup 0< until 2drop ;
- barrym95838
- Posts: 2056
- Joined: 30 Jun 2013
- Location: Sacramento, CA, USA
Re: Introducing Tali Forth for the 65c02 (ALPHA)
In native_words.asm:
Save 4 bytes with:
Save 6 bytes with:
Save 1 byte with:
Save 13 bytes with:
Save 28 bytes with:
These are all untested, and cmove_up is highly experimental.
Mike B.
Save 4 bytes with:
Code: Select all
_stack_ok:
; Display system prompt if all went well. If we're interpreting,
; this is " ok", if we're compiling, it's " compiled"
lda state
beq _print ; zero is "ok" string
lda #1 ; one is "compiled" string
_print:
jsr print_string
; Awesome line, everybody! Now get the next one
bra _get_line
z_cold:
z_abort:
z_quit: ; no RTS required
Code: Select all
; ## BOUNDS ( addr u -- addr+u addr ) "Prepare address for looping"
; ## "bounds" src: Gforth b: 36 c: TBA status: tested
; """Given a string, return the correct Data Stack parameters for
; a DO/LOOP loop; over its characters. This is realized as
; OVER + SWAP in Forth, but we do it a lot faster in assembler
; """
xt_bounds:
cpx #dsp0-3
bmi +
lda #11 ; underflow
jmp error
*
clc
lda 0,x ; <u
ldy 2,x ; <addr
adc 2,x
sta 2,x ; <(addr+u)
sty 0,x ; <addr
lda 1,x ; >u
ldy 3,x ; >addr
adc 3,x
sta 3,x ; >(addr+u)
sty 1,x ; >addr
z_bounds: rts
Code: Select all
; ## CELL_PLUS ( u -- u ) "Add cell size in bytes"
; ## "cell+" src: ANSI core b: 22 c: TBA status: tested
; """Add the number of bytes ("address units") that one cell needs.
; Since this is an 8 bit machine with 16 bit cells, we add two bytes.
; """
.scope
xt_cell_plus:
cpx #dsp0-1
bmi +
lda #11
jmp error
*
inc 0,x
bne +
inc 1,x
*
inc 0,x
bne z_cell_plus
inc 1,x
z_cell_plus: rts
.scend
Code: Select all
; ## CMOVE ( addr1 addr2 u -- ) "Copy bytes going from low to high"
; ## "cmove" src: ANSI string b: 78 c: TBA status: coded
; """Copy u bytes from addr1 to addr2, going low to high (addr2 is
; larger than addr1). Based on code in Leventhal, Lance A.
; "6502 Assembly Language Routines", p. 201
; """
.scope
xt_cmove:
cpx #dsp0-5
bmi +
lda #11 ; underflow
jmp error
*
; move dst address to where we can work with it
lda 2,x
sta tmp2 ; use tmp2 because easier to remember
lda 3,x
sta tmp2+1
; move src address to where we can work with it
lda 4,x
sta tmp1 ; use tmp1 because easier to remember
lda 5,x
sta tmp1+1
ldy #0
lda 1,x ; number of whole pages to move
beq _dopartial
_page:
lda (tmp1),y
sta (tmp2),y
iny
bne _page
inc tmp1+1
inc tmp2+1
dec 1,x
bne _page
_dopartial:
lda 0,x ; length of last page
beq _done
_partial:
lda (tmp1),y
sta (tmp2),y
iny
dec 0,x
bne _partial
_done: ; clear the stack
txa
clc
adc #6
tax
z_cmove: rts
.scend
Code: Select all
; ## CMOVE_UP ( add1 add2 u -- ) "Copy bytes from high to low"
; ## "cmove>" src: ANSI string b: 93 c: TBA status: coded
; """Note addr1 is larger than ; ; addr2). Based on code in
; Leventhal, Lance A. "6502 Assembly Language Routines", p. 201.
; """
.scope
xt_cmove_up:
cpx #dsp0-5
bmi +
lda #11 ; underflow
jmp error
*
; move dst address to where we can work with it
lda 2,x
sta tmp2 ; use tmp2 because easier to remember
lda 3,x
clc
adc 1,x
sta tmp2+1 ; point to last page of destination
; move src address to where we can work with it
lda 4,x
sta tmp1 ; use tmp1 because easier to remember
lda 5,x
clc
adc 1,x
sta tmp1+1 ; point to last page of source
inc 1,x ; allows us to use bne with dec 1,x below
; move the last partial page first
ldy 0,x ; length of last page
beq _nopartial
_outerloop:
dey
beq _finishpage
_innerloop:
lda (tmp1),y
sta (tmp2),y
dey
bne _innerloop
_finishpage:
lda (tmp1) ; handle y = 0 separately
sta (tmp2)
_nopartial:
dec tmp1+1 ; back up to previous pages
dec tmp2+1
dec 1,x
bne _outerloop
_done:
; clear up the stack and leave
txa
clc
adc #6
tax
z_cmove_up: rts
.scend
Mike B.
-
leepivonka
- Posts: 168
- Joined: 15 Apr 2016
Re: Introducing Tali Forth for the 65c02 (ALPHA)
Here are more possible code change suggestions. I'm still learning the Tali way of things, so these aren't tested code yet.
If you can live without the native & called compilation variants for some routines, it is sometimes much easier to native compile a few bytes of machine code instead of making the runtime routine do it all.
The defer word could native compile
and need no library routine at all.
The >r word could native compile
and the library routine to pop a cell off the parameter stack to registers YA is
The literal word could native compile
and the library routine to push registers YA onto the parameter stack is
If you can live without the native & called compilation variants for some routines, it is sometimes much easier to native compile a few bytes of machine code instead of making the runtime routine do it all.
The defer word could native compile
Code: Select all
jmp defer_abort
The >r word could native compile
Code: Select all
jsr PluYA
phy ;no library routine return address on the control stack to worry about here
pha
Code: Select all
PluYA:
cpx #dsp0-1
bmi +
jmp param_stack_underflowed
*
lda 0,x
ldy 1,x
inx
inx
rts
Code: Select all
lda #<num
ldy #>num
jsr PsuYA
Code: Select all
PsuYA:
; cpx #???
; bpl +
; jmp param_stack_overflowed
*
dex
dex
sta 0,x
sty 1,x
rts
- Attachments
-
- Scot2.txt
- Collection of change ideas
- (7.69 KiB) Downloaded 200 times
Re: Introducing Tali Forth for the 65c02 (ALPHA)
@leepivonka - Thanks for fib, is included!
@Mike - Thanks (again) for the enhancements, I'll be testing them ASAP. For CMOVE and CMOVE>, I first need to define a standardized test "by hand", which I already had for Liara but then didn't think to write down
. I mainly remember it being a pain in the rear ...
As for the division between native and subroutine compile -- the idea is currently to have one routine, and then modify that depending on the size limit given in NC-LIMIT (currently set to zero for testing), with special cases modified by the Always Native (AN) and Never Native (NN) header flags. So if NC-LIMIT is 20, any word with a length less than that will be native compiled (unless it is Always Native anyway). That way, there is only one routine for each word, and the clever stuff is done during compilation.
This actually works quite well for Liara Forth. Take >R, which you correctly say is horrible in subroutine compilation. If you look at https://github.com/scotws/LiaraForth/bl ... forth.tasm starting line 2288 in COMPILE,, you'll see that the code recognizes when it has been asked to native compile one of a bunch of special words like >R. It then strips off the whole push-me-pull-you stack antics required for subroutine jumps and only compiles the little bit left over.
For Tali Forth 2, I plan to include a second step that should strip off the underflow checks on words that have them (those with the new UF flag, soon to be added to the headers) so that native compiled DROP ends up as pure INX INX again. The user will be able to set a flag to decide between stability for developing (underflow checks enabled) or speed when the bugs are gone (no underflow checking).
My hope is that the clever stuff all in one places uses less space than adding a second version of the words to the dictionary, with extra pointers in the header etc. Not sure yet how that will turn out
.
@Mike - Thanks (again) for the enhancements, I'll be testing them ASAP. For CMOVE and CMOVE>, I first need to define a standardized test "by hand", which I already had for Liara but then didn't think to write down
As for the division between native and subroutine compile -- the idea is currently to have one routine, and then modify that depending on the size limit given in NC-LIMIT (currently set to zero for testing), with special cases modified by the Always Native (AN) and Never Native (NN) header flags. So if NC-LIMIT is 20, any word with a length less than that will be native compiled (unless it is Always Native anyway). That way, there is only one routine for each word, and the clever stuff is done during compilation.
This actually works quite well for Liara Forth. Take >R, which you correctly say is horrible in subroutine compilation. If you look at https://github.com/scotws/LiaraForth/bl ... forth.tasm starting line 2288 in COMPILE,, you'll see that the code recognizes when it has been asked to native compile one of a bunch of special words like >R. It then strips off the whole push-me-pull-you stack antics required for subroutine jumps and only compiles the little bit left over.
For Tali Forth 2, I plan to include a second step that should strip off the underflow checks on words that have them (those with the new UF flag, soon to be added to the headers) so that native compiled DROP ends up as pure INX INX again. The user will be able to set a flag to decide between stability for developing (underflow checks enabled) or speed when the bugs are gone (no underflow checking).
My hope is that the clever stuff all in one places uses less space than adding a second version of the words to the dictionary, with extra pointers in the header etc. Not sure yet how that will turn out
Re: Introducing Tali Forth for the 65c02 (ALPHA)
@Mike - both the CMOVE and CMOVE> seem to work after initial testing, thank you again.