Re: [Amforth] Missing DU

2020-03-18 Thread Erich Wälde


Hello Martin,

> Also, a bug in D0>:
> Hmmm, something wrong here I feel:
>
>> (ATmega2560)> decimal  1553994000. d0> .   1572137999. d0> .
>> -1 0  ok

yes there is.

Short answer:

The assembly version produces the wrong result,
when the MostSignificantBit of the lower *word* is set.
> trunk/avr8/words/d-greaterzero.asm

The forth version is ok.
> trunk/common/lib/forth2012/double/d-greater-zero.frt

Workaround: use the forth code.


Sightly longer answer:
> | > $7FFF. d0> .
> | -1  ok
> | > $8000. d0> .
> | 0  ok

The exakt value of the high word (here $) is irrelevant.
The Forth version works as advertised:

> | > : new.d0> 2dup or >r  d0< 0=  r> and 0= 0= ;
> |  ok
> | > $7FFF. new.d0> .
> | -1  ok
> | > $8000. new.d0> .
> | -1  ok


The gory details:

So after a dive into the assembly code, reading the docs and a
fair amount of head scratching I think I see cause of the
problem:


#+name: trunk/avr8/macros.asm
#+begin_src asm
.macro loadtos
ld tosl, Y+
ld tosh, Y+
.endmacro
#+end_src

#+name: trunk/avr8/words/d-greaterzero.asm
#+begin_src asm
; ( d -- flag )
; Compare
; compares if a double double cell number is greater 0
VE_DGREATERZERO:
.dw $ff03   ; flags,length
.db "d0>",0 ; name
.dw VE_HEAD ; link to previous voc entry
.set VE_HEAD = VE_DGREATERZERO ; advance pointer to first voc entry
XT_DGREATERZERO:; XT eXecution Token is here
.dw PFA_DGREATERZERO; branch to PFA, this is an assembly word
PFA_DGREATERZERO:   ; so PFA is right here!

cp tosl, zerol  ; comparetop-of-stack-low,  zero-low
cpc tosh, zeroh ; compare-with-carry top-of-stack-high, zero-high

; The result at this point is stored as flags in the STATUS
; register. The original values are left unchanged.

loadtos ; *I guess at this point*
; TOS resides in a register pair
; Y points to the remainder of the stack
;   in RAM. So loadtos moves the former
;   TOS-1 element into register pair tos
; does ld change the status register flags? nope.

cpc tosl, zerol ; compare-with-carry top-of-stack-1-low,  zero-low
cpc tosh, zeroh ; compare-widh-carry top-of-stack-1-high, zero-high

; at this point we have consumed 4 Register values and compared
; them with zero. Reading up on the exact workings of "cp" and
; "cpc" I conclude
;
; cp Rd, Rr
; calculates R = Rd - Rr
; and stores the flags derived from the result R in the status
; register. In particular
;
; Flag Z is set if all bits of the result R are cleared.
;
; Flag S (Signed) = N xor V
;
; Flag N (Negative) is set when R7 (MSB in R) ist set, clear
;otherwise
;
; Flag V (oVerflow) is set if calculating the result produces a
;2 complements overflow.
;since Rr is zero, there should never be such an
;overflow. So in this case V=0.
;
; The S flag is set, if any of the 4 Bytes (== 2 words) have
; their MSB set. That's what we see in the example above.
;

brlt PFA_ZERO1  ; Branch if Less Than, Signed
; Tests the signed flag and branches, if S is set
; at this point, the S flag is used. I currently think that only
; the MSB of the highest Byte should be inspected for this
; decision.

brbs 1, PFA_ZERO1   ; Branch if Status Flag Set, bit 1 (Z) is used
; however, at this point the Z flag is used! Therefore the lower
; Bytes must have been inspected as well!

rjmp PFA_TRUE1  ; jump, (tail call opt.)

; --
PFA_ZERO1:
movw tosl, zerol; copy 0,0 to tosl,h
jmp_ DO_NEXT

; --
PFA_TRUE1:
ser tosl; ser set all bits in register
ser tosh
jmp_ DO_NEXT
#+end_src

I'm not sure I have yet understood the problem in all details.
E.g. the error should show up as well, if only the MSB of a
lower Byte is set.
> | > $0080. d0> .
> | -1  ok
> | > $8000. d0> .
> | 0  ok
> | > $0080. d0> .
> | -1  ok
> | > $8000. d0> .
> | -1  ok
But that is not the case.

Moreover I'm uncertain, how to fix this, or whether the assembly
version should just be removed. Inspecting the code tree
reveals, that this file was added in Version 5.2 and was
unchanged ever since. So it never has worked, it seems.


Any suggestions?
Happy Hacking.

Cheers,
Erich

--
May the Forth be with you ...


___
Amforth-devel mailing list for http://amforth.sf.net/
Amforth-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amforth-devel


Re: [Amforth] Missing DU

2019-08-26 Thread Tristan Williams
Hello Martin,

> Also, a bug in D0>:
> Hmmm, something wrong here I feel:
> 
> > (ATmega2560)> decimal  1553994000. d0> .   1572137999. d0> .  
> > -1 0  ok  

Yes, you are right. There is something odd with d0>

It seems when the sign[1] of the least significant cell and the most
significant cell is the same, d0> gives the right answer. When they
are different, d0> gives the wrong answer.

[1] with sign defined by state of msb

amforth 6.8 ATmega328P Forthduino
> 0 0 d.
0  ok
> 0 0 d0> . cr
0 

> 1 0 d.
1  ok
> 1 0 d0> . cr
-1 

> 0 1 d.
65536  ok
> 0 1 d0> . cr
-1

> 1 1 d.
65537  ok
> 1 1 d0> . cr
-1 

> -1 0 d.
65535  ok
> -1 0 d0> . cr
0 

> 0 -1 d.
-65536  ok
> 0 -1 d0> . cr
-1 
 
> -1 -1 d.
-1  ok
> -1 -1 d0> . cr
0 

> -1 1 d.
131071  ok
> -1 1 d0> . cr
0 

> 1 -1 d.
-65535  ok
> 1 -1 d0> . cr
-1 

Kind regards,

Tristan

On 26Aug19 07:46, Martin Nicholas via Amforth-devel wrote:
> Not present in 6.8 as far as I can see.
> 
> > 8.6.2.1270 DU< “d-u-less” DOUBLE EXT
> > ( ud1 ud2 -- flag )
> > flag is true if and only if ud1 is less than ud2.
> 
> Also, a bug in D0>:
> Hmmm, something wrong here I feel:
> 
> > (ATmega2560)> decimal  1553994000. d0> .   1572137999. d0> .  
> > -1 0  ok  
> 
> Cheers!
> 
> -- 
> Regards,
> 
> Martin Nicholas.
> 
> E-mail: reply-2...@mgn.org.uk (Address will be valid throughout 2019).
> 
> 
> ___
> Amforth-devel mailing list for http://amforth.sf.net/
> Amforth-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/amforth-devel


___
Amforth-devel mailing list for http://amforth.sf.net/
Amforth-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amforth-devel


[Amforth] Missing DU

2019-08-26 Thread Martin Nicholas via Amforth-devel
Not present in 6.8 as far as I can see.

> 8.6.2.1270 DU< “d-u-less” DOUBLE EXT
> ( ud1 ud2 -- flag )
> flag is true if and only if ud1 is less than ud2.

Also, a bug in D0>:
Hmmm, something wrong here I feel:

> (ATmega2560)> decimal  1553994000. d0> .   1572137999. d0> .  
> -1 0  ok  

Cheers!

-- 
Regards,

Martin Nicholas.

E-mail: reply-2...@mgn.org.uk (Address will be valid throughout 2019).


___
Amforth-devel mailing list for http://amforth.sf.net/
Amforth-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amforth-devel