Z80 Divide by 10

dwight elvey dkelvey at hotmail.com
Sat Jan 26 22:12:01 CST 2008


> From: dkelvey at hotmail.com
>
>> Date: Sat, 26 Jan 2008 17:21:56 -0500
>> From: spc at conman.org
>> To: cctalk at classiccmp.org
>> Subject: Re: Z80 Divide by 10
>>
>> It was thus said that the Great dwight elvey once stated:
>>>
>>> 230 clock cycles and no conditionals
>>> Dwight
>>
>> I came across this bit of code from http://www.hackersdelight.org/ to
>> divide by 10:
>>
>> unsigned int div10(unsigned int n)
>> {
>> unsigned int q;
>> unsigned int r;
>>
>> q = (n>> 1) + (n>> 2);
>> q = q + (q>> 4);
>> q = q + (q>> 8);
>> q = q + (q>> 16);
>> q = q>> 3;
>> r = n - ((q << 3) + (q << 1));
>> return (q + ((r + 6)>> 4);
>> }
>>
>> On the Z80, the (q>> 8) is trivial to handle, and you can probably skip
>> the (q>> 16) statement all-to-gether (since you're only handling 16 bits
>> anyway, this reduces to 0 so the statement there can be skipped). My Z80
>> skills are pretty weak (and I don't have any references at hand right now)
>> but this looks pretty straight forward to translate.
>>
> Hi
> I coded this up in Forth and it does good at the divide.
> The values q and r are not much good, meaning one still
> has to calculate the remainder, similar to the last part of my
> code.
> The operation>> is really tough on a Z80 for 16 bit operations.
> One needs to do thing through the a register and use rra instructions
> or use the rr r instruction with a clearing of the carry before each
> single bit shift. Not having a parameterized shift like the 386 has
> makes it difficult.
> I doubt one could beat the 230 cycles I had since each shift cost
> 12 cycles. This is 34 to 38 shifts depending on optimization or 408
> cycles minimum without the 7 16 bit adds. This is already more
> than the 230 cycles.
> It might perform quite well on a machine with a native parameterize
> right shift.
> Dwight
>

I forgot to show my non-optimized Forth code:

: D10s ( n - q r Returned )
 dup 2/
 dup 2/ +
 dup 2/ 2/ 2/ 2/ +
 dup 2/ 2/ 2/ 2/ 2/ 2/ 2/ 2/ +
( skipping the 16 shifts )
2/ 2/ 2/
swap over dup 2* 2* 2* swap 2* + -
2dup 6 + 2/ 2/ 2/ 2/ + ;


: TestD10s ( - ) ( prints results 0 to 799 )
( displays: n Returned r q )
800 0 do
i . i D10s . . . cr
i 20 mod 0= 
if key drop cr then
loop ;

 The Forth version I have does have a parameterized
shift but I wanted to code similar to what I'd deal with
in assembly. 2/ isn't unsigned on my Forth but for numbers
up to 800, that is no problem. I typed this in with indents
but hot mail strips leading spaces :(
Dwight

_________________________________________________________________
Helping your favorite cause is as easy as instant messaging. You IM, we give.
http://im.live.com/Messenger/IM/Home/?source=text_hotmail_join



More information about the cctech mailing list