# Fixed-point unit for the Atari ST

Hi MiKRO !sorry for that late reply - but "better late, then never" : )....

concerning the source i have to say that it's a pretty old one and i neither have looked at them, nor i have used them for many years now, so instead of discussing your questions, i'll give you a little essay on the fixed-point-representation - if you've understood the basics you should easily be able to directly write streamlined fixed-point code instead of using a library everytime ... fixed-point will almost ever be a better choice on the m680x0 series as the 6888x FPUs developed by motorola aren't "the real thing", so, you know ; )....

## so let's start

if you deal with fractions in decimal you write something like fx.

23.34

so as long as you know you'll use a certain range of numbers you'd be able to put the point at a certain place hence "fixed-point" - using 2 fractional places the point would be put like in the above example - here are some others...

14.32

67.56 etc.

so as soon as you need fractional numbers in your code you first have to decide, what will be the largest and smaller number. next you'll decide how many fractional places you will or you still can use after having chosen the range - the more fractional places the more accuracy you may gain in your numbers as well as in your demo-screens or anything - but as the point will stay on a fixed position, different to floating-point, this choice will be a tradeoff all the time - anyway fixed-point is faster on m680x0 machines, at least faster then CPU emulated floats ; ).

so here comes the basic idea - as well as you can put the point at a certain position in the decimal-system, you might do the same in any system let's say hex- or binary or anything... let's take a range of -128 to 127 - using a 16 bit number the integer part will be in the upper 8 bits of those, the lower 8 bits will be left for the fractional part, like this

` upper byte . lower byte `

int . frac

this means that all your numbers stored in 8.8 fixedpoint will be 256 times greater then they really are...pi would become 3.14159*256 => 804 = $324 hex and so on.

to use this in assembly you write:

` move.w #123*256/100,D0`

to store 1.23 for example

you may deal with those numbers as if they were integers as long as you add, sub them. as well you might mul or div them by an integer but as soon as you multiply or divide 2 fixed-numbers you have to watch out:

## mul

all the numbers are 256 times bigger so -> FP_2 \cdot FP_2 = x \cdot 256 \cdot y \cdot 256 = x \cdot y \cdot 65536 , as you use 8 bits accuracy ("256x bigger") you have to divide by 256 again to readjust the fractional part - this can be done quick by downshifting 8 bits again:

` muls.w D0,D1 `

asr.l #8,D1

## div

dividing 2 fp-numbers would kill the fractional part:

(div is an integer operation on the m680x0, of course)

hence you have to upshift before:

` ext.l D1 `

asl.l #8,D1

divs.w D0,D1

there you go...

as soon as you'll take a fp-number under consideration, for calculating an offset etc., it comes in handy to round or truncate it, to get the result of the actions you've performed before:

truncating works by cutting off the fractional part: `asr.w #8,D0;`

now D0 keeps trunc(D0), if D0 has been an 8.8 fp# before

rounding works by adding 0.5 before truncating which is $80 in 8.8fp:

` add.w #$80,D0 `

asr.w #8,D0 ; D0 now holds the rounded number....

that's all to say, i guess.

well of course you may use 32 bit numbers as well. then you may gain a lot of accuracy by using 20.10 fixed-point or anything else (use 10 as shift value then of course and 2^{10} = 1024 as factor instead of 256 for calculating you numbers).

any combination is legal as long as it stays in range (watch out for overflows, though)...

look at sin/cos numbers, here you could use 2.14 fixed-point (2 bits to keep the sign...and sin or cos ranges are [-1;1]).

every kind has its own advantages and disadvantages - just try and error some bit and you'll know how to use this method which is really fine ; )

i hope i could help you out - if i misunderstood you and you already knew how to use the fixed-point representation, then i'm really sorry = )..

cheers,

ray//.tSCc. aka reimund

eof

## FP8_8.S

`*********************************************************************** `

* 8.8 fixedpoint math-untit for ATARI ST (c) 2000 Reimund Dratwa *

* *

* Hi to all Atari-Coders out there , *

* this is my new fixedpoint handler for 68k asm. Since the ATARI STs *

* don´t have an FPU this could be a quick and simple alternative to *

* floating-point calculations. *

* All needed routs are included - I´ll use this stuff for my *

* "ATARI ST Wolf 3D - Clone" project. *

* *

* Values (and results) have to be between -128.00 and +127.99 *

* (in fact that's called 7.8 fixedpoint because numbers are signed) *

* *

* Notice : this unit is not a "stand-alone" program ! But you can *

* include those procs into your own code freely. *

***********************************************************************

* *

* Coming soon: - 16.16 fixedpoint unit *

* - Wolf 3D ! for the ATARI ST *

* *

* if You got questions or problems contact: reimund.dratwa@freenet.de *

* *

***********************************************************************

move.w #fp8_8pi,d0

move.w #$0200,d1

bsr mul_fp

fp8_8pi EQU $0324 * might be useful for some of you - and

* by the way ,i'm going to inculde some

* trigonometric-functions, next time.

* this one converts a fixedpoint value to an integer

* input - d0

* output - d1

fp_to_int: move.w D0,D1

asr.w #8,D1

rts

* and this converts an integer value to fixedpoint

* input - d0

* output - d1

int_to_fp:

move.w D0,D1

asl.w #8,D1

rts

* those two routs add or subtract fixedpoint numbers.

* if I were you i wouldn't use these two at all ,`cause hey,

* you can add and subtract fp numbers without any

* modification.

* Add

* input - d0,d1

* output - d1

add_fp: add.w D0,D1

rts

* Subtract

* input - d0,d1

* output - d1 (d1 = d1 - d0)

sub_fp: sub.w D0,D1

rts

* that's the "complicated" part. here we multiplicate and

* divide fixedpoint numbers.

* division

* input - d0,d1

* output - d1 (d1 = d1 / d0) fp

div_fp: asr.w #4,D0

divs D0,D1

asl.w #4,D1

rts

* multiplication

* input - d0,d1

* output - d1

mul_fp: divs #16,D1

asr.w #4,D0

muls D0,D1

rts

END