I am trying to use an assembly(ARM) macro for fixed-point multiplication:
    #define MULT(a,b) __asm__ __volatile__ ( \
        "SMULL r2, r3, %0, %1\n\t" \
        "ADD r2, r2, #0x8000\n\t" \
        "ADC r3, r3, #0\n\t" \
        "MOV %0, r2, ASR#16\n\t" \
        "ORR %0, %0, r3, ASL#16" \
        : "=r" (a) : "0"(a), "1"(b) : "r2", "r3" );
but when trying to compile I get error(s): expected expression before 'asm'
(You can ignore everything below this if you value your time but it would be nice if you took a look at it, the main question here is how to make the above work)
I tried this:
    static inline GLfixed MULT(GLfixed a, GLfixed b){
       asm volatile(
        "SMULL r2, r3, %[a], %[b]\n"
        "ADD r2, r2, #0x8000\n"
        "ADC r3, r3, #0\n"
        "MOV %[a], r2, ASR#16\n"
        "ORR %[a], %[a], r3, ASL#16\n"
        : "=r" (a)
        : [a] "r" (a), [b] "r" (b)
        : "r2", "r3");
     return a; }
This compiles but there seems to be a problem because when I use constants ex: MULT(65536,65536) it works but when I use variables it seems to f**k up:
GLfixed m[16];
m[0]=costab[player_ry];//1(65536 integer representation)
m[5]=costab[player_rx];//1(65536 integer representation)
m[6]=-sintab[player_rx];//0
m[8]=-sintab[player_ry];//0
LOG("%i,%i,%i",m[6],m[8],MULT(m[6],m[8]));
m[1]=MULT(m[6],m[8]);
m[2]=MULT(m[5],-m[8]);
m[9]=MULT(-m[6],m[0]);
m[10]=MULT(m[5],m[0]);
m[12]=MULT(m[0],0)+MULT(m[8],0);
m[13]=MULT(m[1],0)+MULT(m[5],0)+MULT(m[9],0);
m[14]=MULT(m[2],0)+MULT(m[6],0)+MULT(m[10],0);
m[15]=0x00010000;//1(65536 integer representation)
int i=0;
while(i<16)
{
    LOG("%i,%i,%i,%i",m[i],m[i+1],m[i+2],m[i+3]);
    i+=4;
}
The above code will print(LOG is like printf here):
0,0,-1411346156
65536,65536,65536,440
-2134820096,65536,0,-1345274311
0,65536,22,220
65536,196608,131072,65536
When the correct result would be(obviously alot of junk in the above):
0,0,0
65536,0,0,0
0,65536,0,0
0,0,65536,0
0,0,0,65536
                The first part is easy enough: the problem is that an __asm__ block is a statement, not an expression.
You can use GCC's statement expressions extension to achieve what you want - something like this:
#define MULT(a,b) \
  ({ \
    __asm__ __volatile__ ( \
      /* ... asm stuff here ... */
    ); \
    a; \
  })
The second part is due to problems in the input and output operand specifications. You have two different versions here, and both are wrong. In the macro version, you've said:
: "=r" (a) : "0"(a), "1"(b) : "r2", "r3"
which constrains
a to a register (this is operand 0);a to be the same as operand 0, i.e. the same register (this is operand 1);b to be the same as operand 1, i.e. the same again (this is operand 2).You need "r"(b) here, and can refer to it as %2.
In the inline version, you've said:
: "=r" (a) : [a] "r" (a), [b] "r" (b) : "r2", "r3"
which constrains the output a and the input a and b to registers, but
%0).You should be able to fix the original version with:
: "=r" (a) : "0" (a), "r" (b) : "r2", "r3"
and refer to the a as either %0 or %1, and b as %2.
The inline version can be fixed like this:
: [a] "=r" (a) : "[a]" (a), [b] "r" (b) : "r2", "r3"
and refer the operands as %[a] and %[b].
If you want to use names in the macro version, you'll need something along the lines of
: [arg_a] "=r" (a) : "[arg_a]" (a), [arg_b] "r" (b) : "r2", "r3"
(and refer to %[arg_a] and %[arg_b]) because otherwise the preprocessor will expand the a and b inside [a] and [b].
Note the subtlety in the named argument cases: when a name is being given to an argument (as in the output a) you write [a] - no quotes - but when you are referring to the name of another already-named operand (as in the input a) you need to put it inside quotes: "[a]".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With