Common D< Forth bug

Topics relating to various Forth models on the 6502, 65816, and related microprocessors and microcontrollers.
edx
Posts: 14
Joined: 14 Sep 2014

Re: Common D< Forth bug

Post by edx »

barrym95838 wrote:
edx wrote:
... particularly when there is D< to handle the exceptional cases.
But that was Garth's original beef. D< DIDN'T handle the exceptional cases for him, and he had to re-write the primitive.
I can only go by comments made here which suggests the 'bug fix' was driven by expectations rather than practical necessity ...
Quote:
Any way you look at it, for D< to say that -70007FFF was not less than 0FFF8002 in signed 32-bit numbers is just plain wrong.
...
D< is not used that much
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Common D< Forth bug

Post by GARTHWILSON »

edx wrote:
I can only go by comments made here which suggests the 'bug fix' was driven by expectations rather than practical necessity ...
It did come up in a project, the automated test equipment, but I don't remember the exact context within the project. I had to debug a routine, and it turned out there was nothing wrong with my routine but in the D< that was supplied.
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?
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Common D< Forth bug

Post by BigEd »

I'm tending to agree with the idea that D< does work OK, according to the documentation, but it's an odd spec. It's not signed double size arithmetic, it's something else that's double-sized. Something which is in fact convenient and useful for some applications (timers) and is fine for numerical computation so long as the inputs are relatively close. Garth's failing case has inputs which are very distant.

It would be better for most of us, probably, if the spec had been more straightforward, and the arithmetic was signed double size. Perhaps T< would be a better name (T for timer)

Cheers
Ed
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Common D< Forth bug

Post by GARTHWILSON »

Or... they could just make it work right for all signed double-number pairs, as its name suggests. That would be easier than explaining what the conditions are under which you shouldn't use it. :D
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?
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Common D< Forth bug

Post by BigEd »

If it's right for double sized signed arithmetic, then surely it would be wrong for timer arithmetic?
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Common D< Forth bug

Post by GARTHWILSON »

That's a bit different. What I do with timers, and have done many, many times in multitasking in microcontroller projects to see if it's time for something, is to take the current timer value and subtract the target time calculated earlier, and if the result is negative (ie, high bit set), know that we're not there yet. If it's clear, it's time to do it. So if the current timer value (which might be in arbitrary increments of for example 6ms) is 7F12, target values of 7F13 and 8002 and EFF0 would all yield a negative result, meaning we're not there yet. Enough bits are used such that it will always get checked at less than half way around the circle, so it can't be fooled. It works regardless of what part of the circle you're in. The last project kept four bytes, but depending on what a particular part of the program needed, only bytes 0 and 1 would be used, or only 1 and 2, or oly 2 and 3.
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?
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Common D< Forth bug

Post by BigEd »

Sounds like you've adopted the same clock-based arithmetic that D< gives you...
SamCoVT
Posts: 344
Joined: 13 May 2018

Re: Common D< Forth bug

Post by SamCoVT »

GARTHWILSON wrote:
I redefined it in 6502 Forth as:

Code: Select all

: D<  ROT
      2DUP =
      IF 2DROP U< EXIT THEN
      > -ROT 2DROP  ;
I hope it's OK to bring up an old thread, but I'm super happy to see your version of D< as I just got done writing it myself and I wasn't completely certain I had it correct. Mine looks like:

Code: Select all

: D<   ( d1 d2 -- flag )  ( flag is true iff d1 < d2 )
  rot 2dup =  if 2drop u<  else 2swap 2drop > then ;
They end a little differently, but I think they do the same thing. It looks like your version is slightly better in terms of jumping and stack thrashing. I can now see that it's good practice to perform any operations that reduce the stack size before operations that shuffle the stack, when possible.
JimBoyd
Posts: 931
Joined: 05 May 2017

Re: Common D< Forth bug

Post by JimBoyd »

barrym95838 wrote:
To me, it's not a matter of modern vs. vintage, but more of a matter of correct vs. incorrect. The 6502's overflow flag worked correctly for signed binary from its inception ... it was up to the programmer to make proper use of it. In the case of Forth, I believe that access to the overflow flag was limited for application programs, so that duty should have fallen on the person writing the primitives.
That's an interesting idea. I suppose if someone wanted to implement < and D< as high level and keep them as fast as possible, one wild idea would be to write the subtraction primitives ( - and D- ) so that if there was an overflow they would store -1 in a variable named OVERFLOW and store a zero in it otherwise. Better yet, use a VALUE or soft constant. The high level D< could then be:

Code: Select all

: D<   D- D0< OVERFLOW XOR ;
I've never tried this so I don't know if the overall size would be smaller. It just seems simpler to have < and D< as primitives that test the processors overflow flag.
Quote:
The discussion in Section 2.2.2 makes clever use of the phrases "handles the vast majority" and "is generally safe", so I guess it boiled down to a matter of efficiency vs. exhaustive correctness. I have little doubt that a non-zero percentage of modern software hides similar trade-offs, documented or not.

Mike
Section 2.2.2 also states that different behaviour can be expected from different versions of polyforth.
Quote:
16 bit versions of polyFORTH ISD-4 use the fully signed model (option “a” in Fig. 2.1) to implement most
relationals, as well as MAX and MIN. 32-bit versions of polyFORTH use the circular model.
Post Reply