Archived

This topic is now archived and is closed to further replies.

marijnh

Fixed point divide/multiply macro's in gcc

Recommended Posts

marijnh    182
I''ve been having trouble dividing and multiplying 16.16 fixed point numbers. As far as i can see standard c++ does not provide methods for working with 64 bit numbers, so you have to write the routines in assembly. So far there is no problem. But obviously the methods to multiply and divide have to be inline functions or macro''s because calling a function every time you need a mul/div will really slow things down. Since i am using gcc the #pragma approach does not seem to work. What i have come up with so far are asm macro''s: [begin source code] #define fixmul(a, b) ({ \ long fixrv; \ asm volatile("imull %%edx\n" \ "shrd $16, %%edx, %%eax" \ : "=a" (fixrv) \ : "a" (a), "d" (b)\ ); \ fixrv; \ }) #define fixdiv(a, b) ({ \ long fixrv; \ asm volatile ("movl %%eax, %%edx\n" \ "shll $16, %%eax\n" \ "sarl $16, %%edx\n" \ "idivl %%ecx" \ : "=a" (fixrv) \ : "a" (a), "c" (b)\ : "%edx"); \ fixrv; \ }) [end source code] Note that the asm in in at&t syntax not intel syntax, that is what gcc works with. These macro''s work fine when not optimizing, but when compiling with -O2 the results of calling these become unpredictable. Note that i did specify the clobbered register d for the div macro. When i do the same with and inline function problem still occurs. Does anyone know what goes wrong here, or does anyone know of macro''s with the same functionaly that do work with gcc? Thanks. Marijn

Share this post


Link to post
Share on other sites
I think you will be able to use ''long long'' for 64 bit ints in gcc. That''s what we used for 64 bit maths with the PS1 compiler (which is gcc).

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Share this post


Link to post
Share on other sites
marijnh    182
Ah, i didnt know that. Thanks.
Problem with the macro turned out to be that gcc assumes input registers do not get changed unless they are also specified as output registers, and in this case i shifted edx all over the place so when optimizing it wrongly assumed the old value still was in there and went on with a wrong value.

Marijn

Share this post


Link to post
Share on other sites