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

All times are UTC




Post new topic Reply to topic  [ 40 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
 Post subject: Re: '816 Forths
PostPosted: Wed Jan 11, 2017 3:50 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
BigDumbDinosaur wrote:
As for the JMP ($xxFF) bug, that's an NMOS aberration that was eliminated in the 65C02. New designs should not be using NMOS parts.
whartung isn't advocating the use of NMOS parts. I believe he's drawing a parallel, as follows. In regard to inline code execution, the '816 requires special attention at the boundary between banks -- you need to avoid the boundary (or perhaps use a JML to patch over it). This has similarities to the challenge presented by the NMOS JMP ($xxFF) bug, which in a Forth context resulted in the need for special attention at the boundary between pages. ITC Forth includes in the preamble for each word an operand for an indirect JMP, and with NMOS this operand must not straddle a page boundary.

A workaround was found for the page-boundary problem. The bank-boundary problem, though of a different nature, can be worked around, too.

GARTHWILSON wrote:
you'd have to move an address to N in DP anyway to read or write the final effective address via a long indirect
Just a reminder, Garth, that when you copy an address (or anything else) from the stack to N (a few bytes of "scratch" workspace in DP ram) you stand to lose reentrancy. It becomes impermissible for an Interrupt Service Routine to use the N area, meaning (among other things) the ISR can't be written in Forth.

It would be nice to do away with the N area entirely. Anything done there could instead be done on stack. But even on '816 the stack approach will usually be slower, so there's a tradeoff one needs to evaluate.

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
 Post subject: Re: '816 Forths
PostPosted: Wed Jan 11, 2017 4:13 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10985
Location: England
Thanks Jeff, that's nice and clear, as ever!


Top
 Profile  
Reply with quote  
 Post subject: Re: '816 Forths
PostPosted: Wed Jan 11, 2017 5:00 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Cheers, Ed. I know Garth has an effective alternative to ISR's written in Forth -- a different tradeoff -- so really I'm just blabbing about the topic in general.

N isn't the only problem area. It's common for the NEXT sequence -- crucial to performance -- to store data in a non-reentrant way. If you're not willing to look at that issue then there's no use worrying about N. You'd have to fix both or else there's no point. :|

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
 Post subject: Re: '816 Forths
PostPosted: Wed Jan 11, 2017 6:06 pm 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 679
In other words, the 65816 has a comparable $xxFFFF "bug". ;)

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
 Post subject: Re: '816 Forths
PostPosted: Wed Jan 11, 2017 7:30 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Dr Jefyll wrote:
GARTHWILSON wrote:
you'd have to move an address to N in DP anyway to read or write the final effective address via a long indirect
Just a reminder, Garth, that when you copy an address (or anything else) from the stack to N (a few bytes of "scratch" workspace in DP ram) you stand to lose reentrancy. It becomes impermissible for an Interrupt Service Routine to use the N area, meaning (among other things) the ISR can't be written in Forth.

See my article on servicing interrupts in high-level Forth with zero overhead. After the interrupt hits, the current Forth primitive is allowed to finish executing before the ISR begins. N's contents are irrelevant when a primitive finishes, and N is never to be used to pass parameters from one primitive to another; so you can even nest ISRs if you like.

NEXT doesn't have to store anything besides the usual W and IP. Return addresses for nesting (with nest and unnest) get stored on the return stack. It's no different for ISRs. They just cut in as if they were in the normally executing code. The stack-based nature of Forth (including data stack) makes it all a natural for Forth, totally re-entrant, and so efficient that the portion of NEXT used for responding to an interrupt is actually shorter than for continuing on with the next instruction in the main Forth code. This makes the relative interrupt response time very fast. We no longer have to increment the instruction pointer IP when going to the interrupt-handling word. If we did, the latter would be replacing the next Forth instruction in the main code instead of merely delaying it.

I've been using this method for 26 years with no problems.

_________________
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  
 Post subject: Re: '816 Forths
PostPosted: Wed Jan 11, 2017 9:00 pm 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 1004
BigDumbDinosaur wrote:
Given the generally compact nature of 6502 machine language, I'm still not seeing much of a problem here. It falls more into the realm of good memory management than anything else. There's nothing to stop the compiler from stuffing multiple CODE functions into any given area of RAM. Surely the CODE compiler can figure out how much space the object code will occupy and plan accordingly.


No, it's not impossible, it's just not something that most of the assemblers think about today.

You have to appreciate how unsophisticated the smaller Forth implementations can be. The historic Forth assemblers are spectacularly effective, yet quite crude. It's part of their charm. They're little more than create a word NOP that all it does is stuff $EA in to the current location, and then increment it. This is why you can have a Forth assembler in a page or two of code. There's reason you can have the Forth runtime, compiler, assembler and an editor in 8K of code. We're not talking MASM and Emacs here. And most of the Forths we see here are equally unsophisticated. But, again, that's part of their charm, that so much can be done with so little.


Top
 Profile  
Reply with quote  
 Post subject: Re: '816 Forths
PostPosted: Wed Jan 11, 2017 9:05 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8505
Location: Midwestern USA
White Flame wrote:
In other words, the 65816 has a comparable $xxFFFF "bug". ;)

I wouldn't characterize it as such, as it appears to be a deliberate design feature. I don't know this for certain, but I suspect the decision to limit a program to a single bank was so relative branches would not have to be concerned with branching into a different bank, which would complicate things over and above page crossings.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
 Post subject: Re: '816 Forths
PostPosted: Tue Jan 17, 2017 6:29 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Dr Jefyll wrote:
To anyone contemplating adding long fetches and stores (or dealing with >16-bit values in any way), I suggest you consider arranging that any cell on stack always has 32 bits available, even if the high word often goes unused. A split stack or "ghost stack" is one of the possible ways to meet this requirement, without the performance penalty some of you will be concerned about (ie; you can still use INX INX to drop an item; you don't need INX INX INX INX).

If you get around to working on this before I do, I hope you'll post about it here. I imagine there will be a few other interesting effects on programs, for example needing 32-bit versions of >R and R> (which, for non-Forthers like BDD, transfer a data-stack cell to and from the return (hardware) stack). A matching split return stack will not be efficient to handle, unless I'm forgetting something. I don't need the result to be ANS-compliant (and I certainly don't want ANS forced on me), but it shouldn't deviate from standards any more than necessary to get the improved performance and easier programming. The Forth I'm running now is mostly Forth-83, with enhancements from Forth Dimensions, Starting Forth, Thinking Forth, ANS, my own experience, and common usage which is somewhat of an informal standard in itself.

_________________
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  
 Post subject: Re: '816 Forths
PostPosted: Tue Jan 17, 2017 6:53 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
I can see some interesting effects too. If you use the ghost stack to store half of the long address bits, it would also be very tempting to use it to store half of the bits of doubles too. So you would need to distinguish between a DROP DROP and a DDROP , a >R >R from a D>R , and an R> R> from a DR> , because only the latters would include the cells from the ghost stack. 2DROP is usually defined as DROP DROP or NIP DROP , and that wouldn't get the same job done as a DDROP , which would actually simplify to a single DROP in a ghost stack implementation. Older "ghost stack unaware" code would have to be carefully checked for incompatibilities like this, including anything else treating a double as a pair of cells instead of a normal+ghost pair.

I'm not going to use a ghost stack in my 65m32 Forth, because chars, cells, execution tokens, floats ... (pretty much everything except doubles) are going to be 32-bits wide. This is not necessarily very good for memory bit utilization, but it sure makes things simple to code. I have noticed a lot of '0' nybbles in my hand-assembled binaries, but I guess that goes with the territory as well ...

Mike B.


Top
 Profile  
Reply with quote  
 Post subject: Re: '816 Forths
PostPosted: Tue Jan 17, 2017 6:39 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
About fetch/store operations, and the terminology: In Forth with 16-bit cells, we're familiar with @ and ! (fetch and store) as well as C@ and C!. They all accept an address from a 16-bit cell on stack, but the data moved by C@ and C! is only byte-wide, even though it's moved to or from a full-width cell on stack. (The high-byte of the cell is ignored by C! and padded to zero by C@.) When you have 32-bit cells the word set needs two new members. The fetch/store words could be named as follows:

  • @ W@ and C@ fetch 32-, 16- and 8-bit values, and
  • ! W! and C! store 32-, 16- and 8-bit values.

The convention -- and this is a matter of preference -- is to name the full-width word as simply as possible ( example: @ ), and to embellish the name for special cases. Example: C@ and W@ are special because they don't handle full-width data. Special names for special functions.

The same can apply in regard to addresses. IOW, the names @ and ! can be taken to mean a full-width address is used. If you want comparable words that only use a 16-bit address they'd be called LOCAL@ and LOCAL! or something along those lines (suggestions welcome). They'd still accept an address from a 32-bit cell on stack, but the high word would be ignored because it's implicit that Bank 0 will be used.

Notice I've chosen to deem 16-bit addresses "special" and to name the corresponding words accordingly. When you open the door beyond 64K you'll have to either patch an extension on your existing naming conventions or else use names that embrace the new (virtual) machine. The decision depends on whether you'd rather have source code that leans toward compatibility with legacy code, or toward compatibility with Forths that run on native 32-bit processors. 8)

Fetch and store could each end up with as many as six variations, so let's be careful to be specific when discussing these. The combinations (where full-width is considered non-special) could be called:

  • @ W@ and C@ use a full address and fetch 32, 16 or 8 bits of data
  • LOCAL@ LOCALW@ and LOCALC@ use a 16-bit address and fetch 32, 16 or 8 bits of data

  • ! W! and C! use a full address and store 32, 16 or 8 bits of data
  • LOCAL! LOCALW! and LOCALC! use a 16-bit address and store 32, 16 or 8 bits of data


Footnote 1: I've mentioned "full width" addresses taken from 32-bit cells. But we know on '816 only 24 bits can be used. The top 8 bits will be ignored.
Footnote 2: for a Forth that's expected to deal predominantly with 32-bit data accessed in a 24-bit space it's worth considering abandoning X and the ghost stack and instead using D (the Direct register) as the data-stack pointer. Despite certain drawbacks, D offers the highly compelling ability to access a 24-bit indirect pointer in situ on "stack" and apply post-indexing via Y -- which is what lets you easily access more than 16 bits of data. (I'm not the only one to come up with the D-as-SP idea; I recall seeing it mentioned by one of the SBX users.)

@Garth, the RStack actually can be efficiently given a ghost, using the 816's d,s (ie; stack-relative) address mode. The d (ie: displacement) in d,s is only 8-bit, but that'll suffice.

@Mike, it's true a ghost stack has many uses beyond extended addresses. Floating-point and perhaps even strings are also possibilities, especially if space for extended ghosting is provided. IOW cells could be allowed to be even larger than 32-bit. Words that don't need the extra space just ignore it.

-- Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
 Post subject: Re: '816 Forths
PostPosted: Tue Jan 17, 2017 11:36 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Since most operations will still be 16-bit (32 is less efficient on the '816 and is not necessary in most cases), how about keeping the normal words for 16-bit, including @ and !, and using something else for the 32-bit operations, in the interest of compact source code and minimizing the need to modify already-working source code. It might go something like this:

  • D@ @ C@ for fetching a double, single, or character (byte), all from a 16-bit address
  • D! ! C! for storing a double, single, or character (byte), all from a 16-bit address
  • LD@ L@ LC@ for fetching a double, single, or character (byte), all from a long (32-bit) address
  • LD! L! LC! for storing a double, single, or character (byte), all from a long (32-bit) address

Quote:
@Garth, the RStack actually can be efficiently split to give it a ghost, using the 816's d,s (ie; stack-relative) address mode. The d (displacement) in d,s is only 8-bit, but that'll suffice.

sr,S? (There's no d,S.) So something like:

Code:
        HEADER "D>R", NOT_IMMEDIATE     ; ( d -- )
DtoR:   PRIMITIVE
        LDA   0,X
        PHA
        LDA   $300,X
        STA   $FF,S
        POP1
 ;-------------------

? This assumes 16-bit A, that the high-cell "ghost" of the return stack is $FD bytes above the regular part (we can rework it and do the "ghost" part first to get them $FF apart, but not $100 apart), and that the high-cell "ghost" of the data stack is in page 3 (arbitrarily set, and using 8-bit index registers). HEADER assembles the header (assuming headers are turned on, ie, we're not assembling headerless code locally or globally) in my ITC Forth, PRIMITIVE lays down the two-byte address of the parameter field in the CFA, and POP1 assembles INX INX JMP NEXT.

_________________
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  
 Post subject: Re: '816 Forths
PostPosted: Wed Jan 18, 2017 3:09 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
As I say, it's a matter of preference whether you give the lengthier names to the local and 16-bit words or to the Long and 32-bit words. And the names don't affect run-time performance. :)

I do think there's an argument for more powerful code, though, in cases where the loss of performance is outweighed by the increase in programmer productivity. If I do an '816 Forth it'll probably implement all the 32-bit ANDs ORs +es and so on, and simply call them AND OR and + (as is the case with my 8086 "F32" which I mentioned). Most or all of the 16-bit versions will be omitted -- I just don't see the need for them! First of all, a lot of the coding I do isn't real-time stuff, just assemblers and other batch jobs. It's clearly more important that the code be quick to write and debug. Secondly, if I ever am forced to turbo-charge an inner loop by using 16-bit values, I'd get a bigger boost by coding that part in assembler -- which will be easy, because it's 16-bit! But that's me, eh. :) Not everyone will have the same outlook.

GARTHWILSON wrote:
we can rework it and do the "ghost" part first to get them $FF apart, but not $100 apart)
No sweat, that's already more than enough separation. As you know, it's common for people to overestimate how much stack space is actually needed. If the ghost were $100 away, that means a total of $200 that's available, for a total of 128 32-bit items -- ie, tons.

As for address-mode terminology, maybe WDC isn't entirely consistent. But d,s and similar notations are used in Table 5-5 and Table 5-6. I merged the two and made myself a little cheat sheet for reference, which I'll share here in case anyone finds it useful. Notice that d usually means "direct" but in two cases means "displacement."
Attachment:
chart excerpt.png
chart excerpt.png [ 18.73 KiB | Viewed 4981 times ]


Attachments:
'816 adr modes.png
'816 adr modes.png [ 39.26 KiB | Viewed 4981 times ]

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
Top
 Profile  
Reply with quote  
 Post subject: Re: '816 Forths
PostPosted: Wed Jan 18, 2017 6:25 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8505
Location: Midwestern USA
Dr Jefyll wrote:
As for address-mode terminology, maybe WDC isn't entirely consistent. But d,s and similar notations are used in Table 5-5 and Table 5-6. I merged the two and made myself a little cheat sheet for reference, which I'll share here in case anyone finds it useful. Notice that d usually means "direct" but in two cases means "displacement."

I used double letters avoid confusion, for example, <dp> for direct page. Ditto with the register names. Not sure how the status register came to be referred to with "P", seeing as how most of the 6502 machine language monitors used "SR".

Anyhow and for what it's worth, here are the register names I use in all my software, and have done so for some 41 years, with updates for the 65C816.

Code:
Symbol  Register Description               Size in Bits
————————————————————————————————————————————————————————
  .A    accumulator LSB (m=1)                     8
  .B    accumulator MSB (m=1)                     8
  .C    accumulator (m=0)                        16
  .X    X-index register (affected by x)        8/16
  .Y    Y-index register (affected by x)        8/16
  DB    Data bank                                 8
  DP    Direct page pointer                      16
  PB    Program bank                              8
  PC    Program counter                          16
  SP    Stack pointer                            16
  SR    Status                                    8
   m    Accumulator/memory size flag              1
   x    Index register size flag                  1
————————————————————————————————————————————————————————

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
 Post subject: Re: '816 Forths
PostPosted: Wed Jan 18, 2017 6:36 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
BigDumbDinosaur wrote:
... Not sure how the status register came to be referred to with "P", seeing as how most of the 6502 machine language monitors used "SR" ...

It's been called "P" from the very beginning, for better or worse:

http://archive.6502.org/datasheets/mos_ ... g_1975.pdf

There is a certain economical precision in single-letter register names, especially on a one-address architecture when your mnemonics are only three letters wide, and "S" was already taken. "F" might have been a better choice ... but that's kind of an 8xxx thing, whereas the 6800 already had set a "P" precedent.

Mike B.


Top
 Profile  
Reply with quote  
 Post subject: Re: '816 Forths
PostPosted: Wed Jan 18, 2017 7:46 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8505
Location: Midwestern USA
barrym95838 wrote:
BigDumbDinosaur wrote:
... Not sure how the status register came to be referred to with "P", seeing as how most of the 6502 machine language monitors used "SR" ...

It's been called "P" from the very beginning, for better or worse:

http://archive.6502.org/datasheets/mos_ ... g_1975.pdf

There is a certain economical precision in single-letter register names, especially on a one-address architecture when your mnemonics are only three letters wide, and "S" was already taken. "F" might have been a better choice ... but that's kind of an 8xxx thing, whereas the 6800 already had set a "P" precedent.

Mike B.

I'm aware of that data sheet. However, in early 1977, my employer of the time started development on a project involving the 6502, and the documentation received from MOS Technology (complete with a hand-scribbled note by Chuck Peddle—can't recall what it was about) referred to the status register as SR. Also, the reference machine language monitor that was provided (as source code) referred to the status register as SR, not P. P never made any sense as a register name—it could be confused with PC, the program counter—and as for economy of expression, two letters vs. one makes no sense as well, compared to the opportunity for confusion. This becomes more an issue with the 65C816, of course, since it has more registers.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 40 posts ]  Go to page Previous  1, 2, 3  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 5 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: