Is this the optimal 6502 NEXT?
Re: Is this the optimal 6502 NEXT?
Also >R R> R@ must look for 2nd cell at stack while runs, because 1st is the real return reference
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Is this the optimal 6502 NEXT?
agsb wrote:
Also >R R> R@ must look for 2nd cell at stack while runs, because 1st is the real return reference
Code: Select all
TOR: .WORD *+2
LDA 1,X
PHA
LDA 0,X
PHA
INX
INX
JMP NEXTR> is:
Code: Select all
RFROM: .WORD *+2
DEX
DEX
PLA
STA 0,X
PLA
STA 1,X
JMP NEXTR@ is:
Code: Select all
R: .WORD *+2
STX XSAVE
TSX
LDA $101,X
PHA
LDA $102,X
LDX XSAVE
JMP PUSHThere's no return address to step over, because they're primitives.
In my 65816 ITC Forth, I have for these:
Code: Select all
HEADER ">R", NOT_IMMEDIATE ; ( n -- ) ; Should be compile-only.
TO_R: PRIMITIVE ; Will crash in command line.
LDA 0,X
PHA
POP1
;-------------------
HEADER "DUP>R", NOT_IMMEDIATE ; ( n -- n )
DUP2R: PRIMITIVE
LDA 0,X
PHA
GO_NEXT
;-------------------
HEADER "R>", NOT_IMMEDIATE ; ( -- n )
R_FR: PRIMITIVE
PLA
DEX2 ; These 2 lines are like JMP PUSH but
PUT_TOS ; 2 bytes longer to save 3 clocks.
;-------------------
HEADER "R@", NOT_IMMEDIATE ; ( -- n )
Rfetch: PRIMITIVE ; I uses this code too.
LDA 1,S ; Stack-relative addressing.
DEX2 ; These 2 lines are like JMP PUSH but
PUT_TOS ; 2 bytes longer to save 3 clocks.
;-------------------(with a little use of short macros to improve the source-code clarity and length, for example PUT_TOS is just STA 0,X followed by a jump to NEXT).
Quote:
Code: Select all
next:
; as is, classic ITC from fig-forth 6502
sty y_save
<snip>The fig-Forth NEXT is this:
Code: Select all
NEXT: LDY #1
LDA (IP),Y
STA W+1
DEY
LDA (IP),Y
STA W
CLC
LDA IP
ADC #2
STA IP
BCC L54
INC IP+1
L54: JMP W-1Note that there's no saving and restoring of Y. Many primitives need Y to start as 0 anyway; and this starts with LDY #1, not 0, then DEY's to 0; so it's already initialized for them. My '816 Forth shortens NEXT quite a bit by using the 816's ability to handle 16 bits at a time, and also putting NEXT in direct page to take advantage of self-modifying code to avoid a couple of indirects, having IP and W be operands of the instructions themselves, rather than separate variables.
I kind of like your idea though of using 0000 in the CFA to indicate a primitive, and anything else to indicate a secondary (also called "colon definition"—we do not call these Forth words "compound words" in English), to save some memory. It would take some experimentation to evaluate the tradeoffs. On the '816, it becomes much more worthwhile to make a lot more words primitives, and in my '816 Forth, I have several hundred, which is partly why my 65816 Forth runs two to three times as fast as my '02 Forth at a given clock rate.
As for TOS (top of stack, the top data-stack cell) in register (basically in the 16-bit accumulator for the 65816), I went through some exercises to see if it would be beneficial, and although there are places where it would be, there are others where it actually adds overhead. So I'd have to actually write an entire kernel and run programs on both kernels to find out if it was a wash or not.
Quote:
sorry long post.
There's no need to apologize. A post should be as long as necessary to make the point, and there are many, many posts on this forum that are much, much longer. A few are like presenting a paper at a conference, which is fine.
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: Is this the optimal 6502 NEXT?
MITC also eliminates JSR/RTS, all goes to be: unnest->next-->leaf? jump : nest
Push all references until a primitive then execute and pull a reference
"There's no return address to step over, because they're primitives." and the return reference is at IP in Fig-Forth, but in MITC it will be at top of return stack
Push all references until a primitive then execute and pull a reference
"There's no return address to step over, because they're primitives." and the return reference is at IP in Fig-Forth, but in MITC it will be at top of return stack
Re: Is this the optimal 6502 NEXT?
GARTHWILSON wrote:
I kind of like your idea though of using 0000 in the CFA to indicate a primitive, and anything else to indicate a secondary (also called "colon definition"—we do not call these Forth words "compound words" in English), to save some memory. It would take some experimentation to evaluate the tradeoffs.
It's not as simple as "if the first cell is 0000 jump to the body of this word otherwise nest". A variable has a code field which does not point to its body, yet it is not a secondary. The same for constants and other child words of CREATE DOES> and CREATE ;CODE . These type of words do not have a code field which points to nest (or docolon) nor do they have a code field which points two bytes forward.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Is this the optimal 6502 NEXT?
Good point. For example, fig-Forth's R@ which I listed above is also used for I (getting a copy of the loop counter), and I's CFA points to R@'s code. There are lots of those.
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: Is this the optimal 6502 NEXT?
Quote:
It's not as simple as "if the first cell is 0000 jump to the body of this word otherwise nest". A variable has a code field which does not point to its body, yet it is not a secondary. The same for constants and other child words of CREATE DOES> and CREATE ;CODE . These type of words do not have a code field which points to nest (or docolon) nor do they have a code field which points two bytes forward.
anyway that's what happen in any Forth: push references, till a primitive, execute it, then pull a reference, repeat
;CODE is a primitive that does a direct jump for a reference (address) wich code ends with jmp unnest.
Any value at top of return stack could be moved without warn, just will be momentarily at 2nd cell while >R R> R@ is running, nothing change
Re: Is this the optimal 6502 NEXT?
agsb wrote:
No problem the reference for those is processed as any compound list of references, same for DOCON, DOVAR, DODOES, etc
anyway that's what happen in any Forth: push references, till a primitive, execute it, then pull a reference, repeat
anyway that's what happen in any Forth: push references, till a primitive, execute it, then pull a reference, repeat
A quick perusal of your pdf file leads me to suspect this is actually a modification of direct threaded code (DTC), not ITC.
agsb wrote:
;CODE is a primitive that does a direct jump for a reference (address) wich code ends with jmp unnest.
;CODE is not a primitive, it compiles another word which is also not a primitive.
From the fig-forth installation manual:
Code: Select all
; CODE
Used in the form:
: cccc .... ;CODE
assembly mnemonics
Stop compilation and terminate a new defining word cccc by compiling (;CODE). Set the CONTEXT vocabulary to ASSEMBLER, assembling to machine code the following mnemonics.
Concerning your use of EXIT . Although the fig-Forth name for unnest is ;S (semicolon S), EXIT has been the name for unnest since the Forth-79 Standard, possibly earlier. It is what semicolon compiles.
Re: Is this the optimal 6502 NEXT?
GARTHWILSON wrote:
Good point. For example, fig-Forth's R@ which I listed above is also used for I (getting a copy of the loop counter), and I's CFA points to R@'s code. There are lots of those.
My Forth's I works differently because its DO LOOP's use the overflow flag to determine when the limit has been crossed in either direction.
There are several words in the kernel which have a code field pointing into another word.
Code: Select all
2NIP FORTH-83 >SLF# VFIND L>NAME N>LINK BODY>
>BODY C! HOLD BUFFER 2SWAP NIP UNDER+
OVER OFF SWAP DUP D+ + 1-
1+ DUP>R DNEGATE NEGATE CMOVE ROFF NOOP
[ 1 0 FALSE TRUE BRANCH DROP
EXIT LEAVE
Re: Is this the optimal 6502 NEXT?
Quote:
Concerning your use of EXIT . Although the fig-Forth name for unnest is ;S (semicolon S), EXIT has been the name for unnest since the Forth-79 Standard, possibly earlier. It is what semicolon compiles.
Quote:
;CODE is not a primitive, it compiles another word which is also not a primitive.
Yes, in fig-Forth, and what it does is a jump for a assembler reference, could easy be a fast primitive. In IMMU it is.
Quote:
A quick perusal of your pdf file leads me to suspect this is actually a modification of direct threaded code (DTC), not ITC.
Also in IMMU there is no JSR/RTS, all forth words are a uniq thread linked with JMPs.
Re: Is this the optimal 6502 NEXT?
Quote:
There are several words in the kernel which have a code field pointing into another word.
Really, as in any Forth, only primitives are executed and any compound is a list of address references.
Sure, some words have a "assembler code" in definition, and that part should be defined as primitive, previously.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Is this the optimal 6502 NEXT?
agsb wrote:
Quote:
A quick perusal of your pdf file leads me to suspect this is actually a modification of direct threaded code (DTC), not ITC.
Quote:
Quote:
Concerning your use of EXIT . Although the fig-Forth name for unnest is ;S (semicolon S), EXIT has been the name for unnest since the Forth-79 Standard, possibly earlier. It is what semicolon compiles.
I spent about 45 minutes searching his materials online. I cannot find any reference to "compound words" in his materials. He calls them "colon words" in a recent video. Again, we do not call them "compound words" in English. Please call them "colon definitions" or "secondaries." These are the standard terms. It was sad to read that he died last June. He did appear to be quite old though. I have separate words for unnest versus EXIT (although their CFAs point to the same code), so if I use the ANS word SEE to de-compile a word, it doesn't stop at an EXIT that's not at the end of the word. As an aside, I see Dr. Ting did not like DO...LOOP, preferring instead FOR...NEXT. The primitive laid down by NEXT (obviously different from the inner loop NEXT which is neither a primitive nor a secondary) is simpler than loop, but more limited in what it can do. I see that Elizabeth Rather, in her book "Forth Application Techniques," ©2010, which is regarding Forth, Inc.'s ANS-compliant SwiftForth, only uses DO...LOOP, not FOR...NEXT. I'll stick with DO...LOOP.
I know we're getting partially off the topic of optimal 6502 NEXTs; but we're 11 years and five pages into into it, and it has more or less run its course; so it's not necessary that everything be so tightly related.
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: Is this the optimal 6502 NEXT?
Quote:
"I spent about 45 minutes searching his materials online. I cannot find any reference to "compound words" in his materials. "
I'm not saying that DTC, SDC must ever use JSR/RST, sorry, I try said that IMMU does not use.
And IMMU does not have ~~ call them "colon definitions" or "secondaries." ~~ because nest and unnest are incorporated to inner address interpreter, there is only primitives and "list of references", and any word could be at CFA, including (do), dovar, docon, dodoes etc
Also DO LOOP +LOOP LEAVE FOR NEXT IF ELSE THEN etc