8.8 Fixed Point arithmetic
8.8 Fixed Point arithmetic
Looking for some working Z80 code for multiplying and dividing *signed* 8.8 Fixed Point numbers.
The example mulfixed8_8 I found at Z80 Heaven seems to output D.E * D.E, rather than H.L * D.E as advertised. (The mul16 subroutine seems to work fine)
And the method I found at cemetech is unsigned only.
(I haven't tried the 8.8 division routine yet!)
Anyone got some go-to routines for these which they have verified working?
The example mulfixed8_8 I found at Z80 Heaven seems to output D.E * D.E, rather than H.L * D.E as advertised. (The mul16 subroutine seems to work fine)
And the method I found at cemetech is unsigned only.
(I haven't tried the 8.8 division routine yet!)
Anyone got some go-to routines for these which they have verified working?
Re: 8.8 Fixed Point arithmetic
Perhaps I have misinterpreted some of the code. This part of mulfixed8_8 wouldn't compile in Pasmo, as the label _: is repeated, e.g.
Which gives:
So I've changed the labels as follows:
But perhaps I have misunderstood what jp [cond ,] +[label] means (I've not seen a + used before a label) and fudged the logic as a result?
Code: Select all
; Now make sure the inputs are positive
xor d ;A now has the value of H, since I XORed it with D twice (cancelling)
jp p,+_ ;if Positive, don't negate
xor a
sub l
ld l,a
sbc a,a
sub h
ld h,a
_:
bit 7,d
jr z,+_
xor a
sub e
ld e,a
sbc a,a
sub d
ld d,a
_:
Code: Select all
ERROR on line 26 of file mulfixed8_8.asm
ERROR: Invalid definition, previously defined as EQU or label
Code: Select all
; Now make sure the inputs are positive
xor d ;A now has the value of H, since I XORed it with D twice (cancelling)
jp p,_1 ;if Positive, don't negate
xor a
sub l
ld l,a
sbc a,a
sub h
ld h,a
_1:
bit 7,d
jp z,_2
xor a
sub e
ld e,a
sbc a,a
sub d
ld d,a[color=#FF0000]
_2:
Re: 8.8 Fixed Point arithmetic
Jump label looks fine. Why you think the multiplication routine doesn't work?
Proud owner of Didaktik M
Re: 8.8 Fixed Point arithmetic
For some 3D stuff I was looking for some 16.8 fixed point maths routines, to reproduce some stuff I did on an ST using 16.16 fixed point with its 32-bit registers. (It was very easy to swap or copy out the 16-bit halves whenever you needed a rounded-off integer). But for the Speccy it meant I'd have to reverse-engineer the 32-bit multiplies and divides I could find and reduce the number of bits involved. No easy task with highly optimised code.
Although I reasoned that the code might run faster if I worked backwards through each step of the calculations, worked out how many bits I needed at each step, and used different sized multiplies / divides as appropriate. It would just take a lot longer to write!
Although I reasoned that the code might run faster if I worked backwards through each step of the calculations, worked out how many bits I needed at each step, and used different sized multiplies / divides as appropriate. It would just take a lot longer to write!
Re: 8.8 Fixed Point arithmetic
I made a super-simple test (4 x 1.5 = 6)
Called with PRINT USR so it will display the value in BC when we RET (though this will be 256x the actual answer as it discards the fixed point, essentially shifting it left 8 times)
Code: Select all
; HL = 4.0
LD H, 4
LD L, 0
; DE = 1.5
LD D, 1
LD E, 128
; H.L = H.L * D.E
CALL mulfixed8_8
; RTB (should be 4*1.5*256 = 1536)
; instead it's 1.5*1.5*256 = 576!!
LD B, H
LD C, L
; LD B, 0
; LD C, H
RET
Result is always D.E * D.E
Re: 8.8 Fixed Point arithmetic
I see the bug. The mul16 computes BC*DE, but the fixed 8.8 pass HL and BC (and BC is copied from DE).
Proud owner of Didaktik M
Re: 8.8 Fixed Point arithmetic
Ugh, how did I not spot this!!! They even state it in the comments Thank you [mention]catmeows[/mention]
; Now we need to put HL in BC to use mul16
ld b,d
ld c,e
call mul16
I also spotted another typo just below (though this won't make the whole thing fail - just wrong overflow value):
;We should check for overflow. If D>0, we will set HL to 0x7FFF
ld a,d
or a
jp z,_3
ld hl,$FFFF
_3:
Re: 8.8 Fixed Point arithmetic
Looks to be working now - thanks again [mention]catmeows[/mention] !
I may be back when I tackle division...
I may be back when I tackle division...
Re: 8.8 Fixed Point arithmetic
You are welcome.
That is quite interesting page about math, thanks for sharing.
That is quite interesting page about math, thanks for sharing.
Proud owner of Didaktik M
Re: 8.8 Fixed Point arithmetic
Yeah, this is why I'm using 8.8 even though, say, 4.12 would give greater precision - quick, hassle-free access of the integer part. Nice!Joefish wrote: ↑Mon Mar 08, 2021 11:59 am It was very easy to swap or copy out the 16-bit halves whenever you needed a rounded-off integer
...
I reasoned that the code might run faster if I worked backwards through each step of the calculations, worked out how many bits I needed at each step, and used different sized multiplies / divides as appropriate. It would just take a lot longer to write!
Picking your routines based on expected input/output values sounds like a neat optimisation! Meanwhile, I'm still trying to get the damn thing working at all... maybe I should fix that first
Re: 8.8 Fixed Point arithmetic
I was coming coming here to ask about floats generally, as I need to handle large numbers in my silly project.
Is using the calc stack with 5-character floats and the built-in commands discouraged? Too slow?
Speed is not a concern for me at the moment.
Thanks,
Mpk
Is using the calc stack with 5-character floats and the built-in commands discouraged? Too slow?
Speed is not a concern for me at the moment.
Thanks,
Mpk
- Einar Saukas
- Bugaboo
- Posts: 3158
- Joined: Wed Nov 15, 2017 2:48 pm
Re: 8.8 Fixed Point arithmetic
Yes, it's much easier but extremely slow.
In this case, I suggest you go ahead and use the calculator stack. It should be much easier to make your project work this way.
Even if speed becomes a concern later, it should be easier to modify a fully working program to replace these routines, instead of implementing everything the hard way from scratch.
Re: 8.8 Fixed Point arithmetic
Alright, thanks!
Slow and steady it is.
Mpk
Slow and steady it is.
Mpk
Re: 8.8 Fixed Point arithmetic
[mention]Mpk[/mention] there are also some z80 floating point libraries, which may give you the best of both worlds?
e.g. https://github.com/Zeda/z80float
I haven't tried them as I'm prioritising speed over accuracy (for now, at least)
e.g. https://github.com/Zeda/z80float
I haven't tried them as I'm prioritising speed over accuracy (for now, at least)
Re: 8.8 Fixed Point arithmetic
Does anyone know of any tutorial / examples for using the calc stack functions?
All I can find is the ROM disassembly pages ( e.g. https://skoolkid.github.io/rom/asm/3014.html) which are thorough, but not very friendly for the neophyte. I can get the multiply working fine, but the addition one just seems to return the top value unaltered. I think I'm not setting the DE/HL pointers correctly.
[mention]presh[/mention] Thanks, I may look at those if I can't get the basic ones working.
All I can find is the ROM disassembly pages ( e.g. https://skoolkid.github.io/rom/asm/3014.html) which are thorough, but not very friendly for the neophyte. I can get the multiply working fine, but the addition one just seems to return the top value unaltered. I think I'm not setting the DE/HL pointers correctly.
[mention]presh[/mention] Thanks, I may look at those if I can't get the basic ones working.
Re: 8.8 Fixed Point arithmetic
Thanks, fixed
The labels with +_ and -_ come from the spasm assembler popular with Texas Instruments Z80 calculators.
Code: Select all
_: is a temporary label,
+_ refers to the closest following _:, and
-_ refers to the closest preceding _:.
I've also put these routines up on GitHub here:
mulfixed_88.z80
divfixed_88.z80
sqrtfixed_88.z80
Since they are up on GitHub, feel free to offer optimizations and routines as well as bug reports. I'm fairly busy these days, but I still do Z80 work at least one day a week.
If you do want to venture into using floats, I recommend the 24-bit floats here (these floats are small enough to be passed in registers!). I'm still working on the routines though, so they are apt to change as I find optimizations, but the inputs/outputs will remain the same. Depending on your project, there are 32-bit float routines, as well as 80-bit float routines in that library (you know, in case you need to do some high-precision computing on your Z80 ).