SM/REM FM/MOD and UM/MOD on a 32bit cell ix86 Forth 
Author Message
 SM/REM FM/MOD and UM/MOD on a 32bit cell ix86 Forth

I've been writing my on Forth, and have had no problems coding any of
the words, but 64bit division seems to be a little bit past me.
Can someone post the code for these words for me, either in ix86
assembly, or high level Forth?

Thanks for your help,
Shaun Jackman



Thu, 07 Jun 2001 03:00:00 GMT  
 SM/REM FM/MOD and UM/MOD on a 32bit cell ix86 Forth


Quote:
>I've been writing my on Forth, and have had no problems coding any of
>the words, but 64bit division seems to be a little bit past me.
>Can someone post the code for these words for me, either in ix86
>assembly, or high level Forth?

An extract from my little Forth works:

\ ------ Double & Mixed Arithmetics
------------------------------------------

_code D+      _dplus    \ ( d1 d2 -- dsum ) add d2 to d1

_code DNEGATE _dnegate  \ ( d -- -d ) negate d

_code MU*     _mustar   \ ( ud u -- udprod ) multiply u to ud

_code MU/MOD  _mudivmod \ ( ud u -- urem udquot ) unsigned double
division

_:    S>D     dup 0< _; \ ( n -- d ) convert single to double number

_:    D=      dnegate d+ or 0= _;  \ ( d1 d2 -- f ) true if d1 = d2

_: DABS    \ ( d -- |d| ) make d absolute
   dup 0< _if dnegate _then _;

_: UM*     \ ( u1 u2 -- ud ) unsigned multiplication with double
result
   0 swap mu* _;

_: M*      \ ( n1 n2 -- d ) signed multiplication with double result
   2dup xor >r abs swap abs um* r> 0< _if dnegate _then _;

_: UM/MOD  \ ( ud u -- r q ) unsigned double division by single
divisor
   mu/mod drop _;    

_: SM/REM  \ ( d m -- r q ) signed symmetric division

swap _;      

_: FM/MOD  \ ( d m -- r q ) signed floored division
   dup >r sm/rem 2dup 0< and _if 1- swap r> + swap _else r> drop _then
_;

_: */MOD   \ ( n1 n2 n3 -- r q ) n1*n2/n3 with double intermediate
result
   >r m* r> sm/rem _;

_: */      \ ( n1 n2 n3 -- q ) n1*n2/n3 with double intermediate
result
   */mod nip _;  

/*
------------------------------------------------------------------------
   Double and mixed arithmetics (for compilers with/out 64bit math)
*/
void pDPLUS() /* ( d1 d2 -- dsum ) */
{
#if MATH_64
   DAddr D1,D2,DRes;
   Indepth(4); DPop(&D1), DPop(&D2);
   DRes = D1 + D2;
   DPush(&DRes);
#else
   Addr d2h,d2l,d1l;
   Indepth(4); d2h = POP(), d2l=POP(), d1l = SECOND;
   d2l += d1l; if (d2l < d1l) d2h++;
   SECOND = d2l, TOS += d2h;
#endif

Quote:
}

void pDNEGATE() /* ( d -- -d ) */
{
#if MATH_64
   DAddr D1,DRes;
   Indepth(2); DPop(&D1);
   DRes = -D1;
   DPush(&DRes);
#else
   Indepth(2);
   TOS = -TOS;
   if (SECOND = -SECOND) TOS -= 1;
#endif

Quote:
}

void pMUSTAR() /* ( ud1 u2 -- udprod ) unsigned */
{  Addr u;
#if MATH_64
   DAddr UD1, UDRes;
   Indepth(3); u = POP(); DPop(&UD1);
   UDRes = UD1 * u;
   DPush(&UDRes);
#else
   Addr ul, uh, al, ah, a, b;
   Indepth(3); u = POP(), a = SECOND, b = TOS;
   ah = a >> 16, al = a & 0xffff, uh = u >> 16, ul = u & 0xffff;
   SECOND = a * u, TOS = b * u + ah * uh;
   a = uh * al, b = a + ul * ah + ((ul * al)>>16),
   u = b >> 16; if (a > b) u |= 0x10000l;
   TOS += u;
#endif

Quote:
}

void pMUDIVMOD() /* ( ud1 u2 -- urem udquot ) unsigned */
{  Addr u;
#if MATH_64
   DAddr UD1, UD2, UDRes;
   Indepth(3); u = POP(); DPop(&UD1); UD2 = UD1;
   if (u == 0) Throw(-10);
   PUSH((Addr)(UD1 % u));
   UDRes = UD2 / u;
   DPush(&UDRes);
#else
   Addr a,b,c,sa; int i;
   Indepth(3); u = TOS, c = SECOND, b = THIRD;
   if (u == 0) Throw(-10);
   a = c / u, c = c % u;
   for (i=0; i<32; i++)
   {   sa =            c >> 31;
       c = (c << 1) | (b >> 31);
       b = (b << 1) | (a >> 31);
       a =  a << 1;
       if (sa | (c >= u)) c -= u, a += 1; }
   SECOND = a, TOS = b, THIRD = c;
#endif
Quote:
}



Fri, 08 Jun 2001 03:00:00 GMT  
 SM/REM FM/MOD and UM/MOD on a 32bit cell ix86 Forth

Quote:



>>I've been writing my on Forth, and have had no problems coding any of
>>the words, but 64bit division seems to be a little bit past me.
>>Can someone post the code for these words for me, either in ix86
>>assembly, or high level Forth?

Have you looked at the Arith or calc applications? They're in C,
and they use a triple for an int, but they gave me the basic
algorithms for + and #, and they have many others.
http://ftp.lth.se/archive/usenet/comp.sources.unix/volume27/calc-2.9.0/
I think Arith was recently in .../incoming on sunsite, don't recall.

Quote:

>An extract from my little Forth works:

>\ ------ Double & Mixed Arithmetics
>------------------------------------------

>_code D+      _dplus    \ ( d1 d2 -- dsum ) add d2 to d1

>_code DNEGATE _dnegate  \ ( d -- -d ) negate d

>_code MU*     _mustar   \ ( ud u -- udprod ) multiply u to ud

>_code MU/MOD  _mudivmod \ ( ud u -- urem udquot ) unsigned double
>division

>_:    S>D     dup 0< _; \ ( n -- d ) convert single to double number

>_:    D=      dnegate d+ or 0= _;  \ ( d1 d2 -- f ) true if d1 = d2

>_: DABS    \ ( d -- |d| ) make d absolute
>   dup 0< _if dnegate _then _;

>_: UM*     \ ( u1 u2 -- ud ) unsigned multiplication with double
>result
>   0 swap mu* _;

>_: M*      \ ( n1 n2 -- d ) signed multiplication with double result
>   2dup xor >r abs swap abs um* r> 0< _if dnegate _then _;

>_: UM/MOD  \ ( ud u -- r q ) unsigned double division by single
>divisor
>   mu/mod drop _;    

>_: SM/REM  \ ( d m -- r q ) signed symmetric division

>swap _;      

>_: FM/MOD  \ ( d m -- r q ) signed floored division
>   dup >r sm/rem 2dup 0< and _if 1- swap r> + swap _else r> drop _then
>_;

>_: */MOD   \ ( n1 n2 n3 -- r q ) n1*n2/n3 with double intermediate
>result
>   >r m* r> sm/rem _;

>_: */      \ ( n1 n2 n3 -- q ) n1*n2/n3 with double intermediate
>result
>   */mod nip _;  

>/*
>------------------------------------------------------------------------
>   Double and mixed arithmetics (for compilers with/out 64bit math)
>*/
>void pDPLUS() /* ( d1 d2 -- dsum ) */
>{
>#if MATH_64
>   DAddr D1,D2,DRes;
>   Indepth(4); DPop(&D1), DPop(&D2);
>   DRes = D1 + D2;
>   DPush(&DRes);
>#else
>   Addr d2h,d2l,d1l;
>   Indepth(4); d2h = POP(), d2l=POP(), d1l = SECOND;
>   d2l += d1l; if (d2l < d1l) d2h++;
>   SECOND = d2l, TOS += d2h;
>#endif
>}

>void pDNEGATE() /* ( d -- -d ) */
>{
>#if MATH_64
>   DAddr D1,DRes;
>   Indepth(2); DPop(&D1);
>   DRes = -D1;
>   DPush(&DRes);
>#else
>   Indepth(2);
>   TOS = -TOS;
>   if (SECOND = -SECOND) TOS -= 1;
>#endif
>}

>void pMUSTAR() /* ( ud1 u2 -- udprod ) unsigned */
>{  Addr u;
>#if MATH_64
>   DAddr UD1, UDRes;
>   Indepth(3); u = POP(); DPop(&UD1);
>   UDRes = UD1 * u;
>   DPush(&UDRes);
>#else
>   Addr ul, uh, al, ah, a, b;
>   Indepth(3); u = POP(), a = SECOND, b = TOS;
>   ah = a >> 16, al = a & 0xffff, uh = u >> 16, ul = u & 0xffff;
>   SECOND = a * u, TOS = b * u + ah * uh;
>   a = uh * al, b = a + ul * ah + ((ul * al)>>16),
>   u = b >> 16; if (a > b) u |= 0x10000l;
>   TOS += u;
>#endif
>}

>void pMUDIVMOD() /* ( ud1 u2 -- urem udquot ) unsigned */
>{  Addr u;
>#if MATH_64
>   DAddr UD1, UD2, UDRes;
>   Indepth(3); u = POP(); DPop(&UD1); UD2 = UD1;
>   if (u == 0) Throw(-10);
>   PUSH((Addr)(UD1 % u));
>   UDRes = UD2 / u;
>   DPush(&UDRes);
>#else
>   Addr a,b,c,sa; int i;
>   Indepth(3); u = TOS, c = SECOND, b = THIRD;
>   if (u == 0) Throw(-10);
>   a = c / u, c = c % u;
>   for (i=0; i<32; i++)
>   {   sa =            c >> 31;
>       c = (c << 1) | (b >> 31);
>       b = (b << 1) | (a >> 31);
>       a =  a << 1;
>       if (sa | (c >= u)) c -= u, a += 1; }
>   SECOND = a, TOS = b, THIRD = c;
>#endif
>}

--
Rick Hohensee          http://cqi.com/~humbubba
colorg on EFnet IRC    #linux chanop
Forth  C   Linux   Perl graphics   music    Md., USA


Fri, 08 Jun 2001 03:00:00 GMT  
 SM/REM FM/MOD and UM/MOD on a 32bit cell ix86 Forth

Quote:

> I've been writing my on Forth, and have had no problems coding any of
> the words, but 64bit division seems to be a little bit past me.
> Can someone post the code for these words for me, either in ix86
> assembly, or high level Forth?

> Thanks for your help,
> Shaun Jackman

I did all this in x86 asm in JaxForth 1.25 for Windows NT.

The source and exe are posted on

        http://www.*-*-*.com/

--
Jack J. Woehr                 # The Drug War is Race War
PO Box 51, Golden, CO 80402   # The Drug War is Class War.

http://www.*-*-*.com/ ~jax/rcfb # Arrest the War on {*filter*}.



Fri, 08 Jun 2001 03:00:00 GMT  
 SM/REM FM/MOD and UM/MOD on a 32bit cell ix86 Forth

Quote:

> The source and exe are posted on

>         http://www.*-*-*.com/

> --
> Jack J. Woehr                 # The Drug War is Race War
> PO Box 51, Golden, CO 80402   # The Drug War is Class War.

> http://www.*-*-*.com/ ~jax/rcfb # Arrest the War on {*filter*}.

My browser shows a black screen with small dark green letters at the
top:    *(ROCKY COAST FREE BOARD)*

The source is:

<HTML>
<META HTTP-EQUIV="refresh" CONTENT="0; URL=./rcfb/forth.html">
<BODY BGCOLOR="#000000">
<CENTER><IMAGE WIDTH="210" HEIGHT="14" SRC="./gifs/torcfb.gif"></CENTER>
</BODY>
</HTML>
<p><center>

</center>

What do I need to do to read it?

Jerry
--
Engineering is the art       |      Let's talk about what
of making what you want      |      you need; you may see
from things you can get.     |      how to do without it.
---------------------------------------------------------



Sat, 09 Jun 2001 03:00:00 GMT  
 SM/REM FM/MOD and UM/MOD on a 32bit cell ix86 Forth

Quote:


>> The source and exe are posted on

>>         http://www.well.com/user/jax/forth.html
>My browser shows a black screen with small dark green letters at the
>top:    *(ROCKY COAST FREE BOARD)*

>What do I need to do to read it?

        The page has a black background. If your browser is showing
you black text on top of that, it'll be hard to read. Find the option
in your browser that insists on using your own colors, you should be
able to read it. In netscape 4.07 that's        

        Edit/Preferences/Appearance/Colors

and tick the checkbox that says ``Always use my own colors, overriding
document''. I don't know about IE. And in lynx its not a problem.

(
----------
Virtually,

Bruce McFarling, Newcastle,

)



Sat, 09 Jun 2001 03:00:00 GMT  
 SM/REM FM/MOD and UM/MOD on a 32bit cell ix86 Forth

Quote:

>I've been writing my on Forth, and have had no problems coding any of
>the words, but 64bit division seems to be a little bit past me.
>Can someone post the code for these words for me, either in ix86
>assembly, or high level Forth?

>Thanks for your help,
>Shaun Jackman

In x86 assembly,

Register Usage :
eax -- top of the stack
ebp -- stack pointer to the second top item
ecx, edx -- temporay register

CODE SM/REM    ( d n -- rem quo )
        mov    ecx , eax        \ divisor
        mov    edx , [ebp+0]    \ hi 32bit dividend
        mov    eax , [ebp+4]    \ lo 32bit dividend
        add    ebp , 4        \ discard an item
        idiv    ecx
        mov    [ebp+0] , edx    \ remainder
        next            \ inner interpreter
        END-CODE

CODE FM/MOD    ( d n -- rem quo )
        mov    ecx , eax        \ divisor
        mov    edx , [ebp+0]    \ hi 32bit dividend
        mov    eax , [ebp+4]    \ lo 32bit dividend
        add    ebp , 4        \ discard an item
        idiv    ecx
        xor    ecx , edx

        test    edx , edx

        xor    ecx , edx    \ restore divisor
        dec    eax        \ decrement quotient
        add    edx , ecx    \ add divisor to remainder

        next            \ inner interpreter
        END-CODE

Charles Liu



Sat, 09 Jun 2001 03:00:00 GMT  
 SM/REM FM/MOD and UM/MOD on a 32bit cell ix86 Forth

Quote:

> My browser shows a black screen with small dark green letters at the
> top:    *(ROCKY COAST FREE BOARD)*

It's a referral link, should have worked. I've made a visible, clickable
link now on that referral page for browsers which stall. Directly, you
can enter

        http://www.*-*-*.com/

In the words of the Deity in _So Long, and Thanx for All the Fish_,
``We apologize for the incovenience.''

--
Jack J. Woehr                 # The Drug War is Race War
PO Box 51, Golden, CO 80402   # The Drug War is Class War.

http://www.*-*-*.com/ ~jax/rcfb # Arrest the War on {*filter*}.



Sat, 09 Jun 2001 03:00:00 GMT  
 SM/REM FM/MOD and UM/MOD on a 32bit cell ix86 Forth

"L> CODE SM/REM    ( d n -- rem quo )
"L>         mov    ecx , eax        \ divisor
"L>         mov    edx , [ebp+0]    \ hi 32bit dividend
"L>         mov    eax , [ebp+4]    \ lo 32bit dividend
"L>         add    ebp , 4        \ discard an item
"L>         idiv    ecx
"L>         mov    [ebp+0] , edx    \ remainder
"L>         next            \ inner interpreter
"L>         END-CODE

Nice (and nicely written, thank you!). Now just imagine someone were not
satisfied with what the CPU manufacturer offered, and would expect maybe
a trap (as Motorola calls it) in case of a zero divisor, but otherwise
for sure arithmetic as usual.

So to expect:

2147483647 4294967295 1 sm/rem

to deliver:

2147483647 remainder 0,

same way as is expected the following three multiplications not to hang
any machine:

2147483647 dup * u. 1 ok
2147483648 dup * u. 0 ok
2147483647 dup 1+ * u. 2147483648 ok

but silently deliver the result modulo 2^32.

I'd be very glad to meet a rewritten "CODE SM/REM" example as above,
which performs the demands of modulo arithmetic reliably and with no
exceptions on Intel machines (zero denominator excepted). If it exists,
so at least the phrase 'IDIV' for sure will occur twice in it.

I could not find it. Maybe I've overseen something. So long I use UM/MOD
which has proven to be reliable (doing 96/32 bit, 32 bit of 96 to avoid
the overflow; same way, TU/MOD as base for M*/ is for real a
bit-crunching action for 128/32 bit), as a base for a secondary SM/REM.

I think of it more that way: I try to invoke this computing stuff on a
different party than such one where a big war ministry recently was
satisfied (temporarily, I guess) to equip workstations on a battle-ship
with a hand-written note: not to input zeros into specific database
fields, as it might hang the server which controls as well the engines
of the ship and thus the ship might again remain unnavigatable in the
sea for several days...

Now that one was for a well-known OS obviously not being able to recover
from traps in some cases, which is only by analogy related to the above.
But for same in both cases: Just a question of which kind of logic one
thinks is applicable; seems to me better to look for a more consistent
one ;)



Sat, 09 Jun 2001 03:00:00 GMT  
 
 [ 9 post ] 

 Relevant Pages 

1. MOD and /MOD with Pygmy Forth

2. hi-level FM/MOD SM/REM & other maths

3. ANS Source for FM/MOD

4. UM/MOD routine

5. MOD, REM, et al

6. DIV, MOD, /, REM (M2,O2)

7. Query: numeric_std: div,rem,mod

8. function REM or MOD

9. mod vs. rem

10. Need Help with Division/MOD/REM

11. Difference between REM and MOD

12. Utils.Mod, ET.Mod

 

 
Powered by phpBB® Forum Software