6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Nov 22, 2024 2:53 pm

All times are UTC




Post new topic Reply to topic  [ 266 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8, 9, 10 ... 18  Next
Author Message
PostPosted: Mon Mar 05, 2018 7:28 am 
Offline

Joined: Mon Jan 07, 2013 2:42 pm
Posts: 576
Location: Just outside Berlin, Germany
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.


Top
 Profile  
Reply with quote  
PostPosted: Mon Mar 05, 2018 4:07 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
scotws wrote:
... The balance is okay because of the DUP -- IF always eats one I and . (that's DOT) always prints the other.)

... except that when I is 20 ." is executed instead of . which would leave the duped 20 on the stack because ." doesn't consume it, right?

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.


Top
 Profile  
Reply with quote  
PostPosted: Mon Mar 05, 2018 7:16 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
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?


Top
 Profile  
Reply with quote  
PostPosted: Mon Mar 05, 2018 8:39 pm 
Offline

Joined: Mon Jan 07, 2013 2:42 pm
Posts: 576
Location: Just outside Berlin, Germany
Well, the inside of the loop looks sort of like this:
Code:
i   ( u )
dup ( u u )
20  ( u u 20 )
=   ( u f )
if  ." twenty " then ( u )
.   (  )
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 :oops: .


Top
 Profile  
Reply with quote  
PostPosted: Mon Mar 05, 2018 9:09 pm 
Offline

Joined: Mon Jan 07, 2013 2:42 pm
Posts: 576
Location: Just outside Berlin, Germany
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 06, 2018 2:42 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
GARTHWILSON wrote:
There's no ELSE or UNLOOP or EXIT or LEAVE or anything that wold keep . from getting executed.

Ah, got it. Please excuse my ignorance.

Mike B.


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 06, 2018 8:30 am 
Offline

Joined: Mon Jan 07, 2013 2:42 pm
Posts: 576
Location: Just outside Berlin, Germany
barrym95838 wrote:
GARTHWILSON wrote:
There's no ELSE or UNLOOP or EXIT or LEAVE or anything that wold keep . from getting executed.
Please excuse my ignorance.
Don't worry, I've given up pretending I'm clever enough to write, let alone read, Forth without stack comments after every single word; I condense it somewhat later, but Forth is always a humbling experience.

This is good example of a line that should be broken into two words anyway:
Code:
: .twenty ( u -- ) 20 = if ." twenty " then ;
followed by
Code:
: aaa  ( -- ) 100 10 do i dup .twenty . loop ;
which is a lot clearer.

(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 ...)


Top
 Profile  
Reply with quote  
PostPosted: Tue Mar 06, 2018 10:08 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
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:
Code:
: AAA
   100 10
   DO  I
       DUP 20 =
       IF ." twenty " THEN
       .
   LOOP          ;

Code:
: 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:
: AAA
   100 10
   DO  I  20 =
       IF ." twenty " THEN
       I  .
   LOOP        ;

(and again, there are several ways to do it).

With exaggerated commenting:
Code:
: 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!  :D  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.

_________________
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?


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 07, 2018 12:03 am 
Offline

Joined: Mon Jan 07, 2013 2:42 pm
Posts: 576
Location: Just outside Berlin, Germany
@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 :D .

@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:
see within
 3C00  ���`��0
 0
 
0000   ok
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!


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 07, 2018 12:30 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
scotws wrote:
@Garth - CONTINUE skips the rest of the loop and goes to the next iteration

Without adding words, CONTINUE might be done this way:
Code:
: 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?


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 07, 2018 6:36 am 
Offline

Joined: Fri Apr 15, 2016 1:03 am
Posts: 140
Here is a Fibonacci routine that prints all the numbers as it goes:
Code:
: fib ( -- )
   0 1 begin dup . swap over + dup 0< until 2drop ;


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 07, 2018 7:04 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
In native_words.asm:

Save 4 bytes with:
Code:
_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


Save 6 bytes with:
Code:
; ## 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


Save 1 byte with:
Code:
; ## 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


Save 13 bytes with:
Code:
; ## 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


Save 28 bytes with:
Code:
; ## 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

These are all untested, and cmove_up is highly experimental.

Mike B.


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 07, 2018 7:07 am 
Offline

Joined: Fri Apr 15, 2016 1:03 am
Posts: 140
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
Code:
   jmp defer_abort

and need no library routine at all.

The >r word could native compile
Code:
   jsr PluYA
   phy     ;no library routine return address on the control stack to worry about here
   pha

and the library routine to pop a cell off the parameter stack to registers YA is
Code:
PluYA:
   cpx #dsp0-1
   bmi +
   jmp param_stack_underflowed
*
   lda 0,x
   ldy 1,x
   inx
   inx
   rts


The literal word could native compile
Code:
   lda #<num
   ldy #>num
   jsr PsuYA

and the library routine to push registers YA onto the parameter stack is
Code:
PsuYA:
;   cpx #???
;   bpl +
;   jmp param_stack_overflowed
*
   dex
   dex
   sta 0,x
   sty 1,x
   rts


Attachments:
File comment: Collection of change ideas
Scot2.txt [7.69 KiB]
Downloaded 188 times
Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 07, 2018 9:42 am 
Offline

Joined: Mon Jan 07, 2013 2:42 pm
Posts: 576
Location: Just outside Berlin, Germany
@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 :) .


Top
 Profile  
Reply with quote  
PostPosted: Sun Mar 11, 2018 2:37 pm 
Offline

Joined: Mon Jan 07, 2013 2:42 pm
Posts: 576
Location: Just outside Berlin, Germany
@Mike - both the CMOVE and CMOVE> seem to work after initial testing, thank you again.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 266 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8, 9, 10 ... 18  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: