0

I am following up on this question and this another one.

In the first post, I can get to make work the following SPARC inline assembly code :

#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>

int n;
int sum;

int main ()
{
  sum = 0;
  n = 1000;

  struct timeval tv1, tv2;
  long int diff;

  gettimeofday (&tv1, NULL);

  asm volatile ("set sum, %g1\n\t" \
                "ld [%g1], %g2\n\t" \
                "set n, %g3\n" \
                "ld [%g3], %g4\n\t" \
                "loop:\n\t" \
                "add %g2, 1, %g2\n\t" \
                "subcc %g4, 1, %g4\n\t" \
                "bne loop\n\t" \
                "nop\n\t"
                "st %g2, [%g1]"
                );

  gettimeofday (&tv2, NULL);

  diff = (tv2.tv_sec - tv1.tv_sec) * 1000000L + (tv2.tv_usec - tv1.tv_usec);
  printf ("Elapsed time = %ld usec\n", diff);

  printf ("Sum = %d\n", sum);

  return 0;

}

The final result is :

Elapsed time = 37 usec
Sum = 1000

which is the expected result.

I think that, by using the instruction : set sum, %g1, I put the address of sum variable into %g1 register. I do the same with n whose address is stored into %g3 register. After, I load the values located at address [%g1] and [%g3] into %g2 and %g4 and handle them. Finally, I store %g2 value at the address of variable sum, i.e located at [%g1].

The only constraint that I have to respect is to declare sum and n outside the int main() function : if I declare them into int main(), the compilation failed.

Now, I am using another syntax which is also used into manuals about Inline Assembly code - this second syntax is the following form :

asm volatile("Sparc instructions" 
    : /* output : don't forget "=" */ "=r" (outputX)
    : /* input */ "r"(inputX)
    : /* no clobbered regs */
    );

this is the subject of second post. The following code works fine :

 #include <stdio.h>
#include <sys/time.h>
#include <unistd.h>

int main ()
{
  int sum = 0;
  int n = 100000000;

  struct timeval tv1, tv2;
  long int diff;

  gettimeofday (&tv1, NULL);

  asm volatile ("clr %%g1\n" \
                "loop:\n\t" \
                "add %%g1, 1, %%g1\n\t" \
                "subcc %1, 1, %1\n\t" \
                "bne loop\n\t" \
                "nop\n\t"
                "mov %%g1, %0\n"
                : "=r" (sum)
                : "r" (n)
                : "g1");

  gettimeofday (&tv2, NULL);

  diff = (tv2.tv_sec - tv1.tv_sec) * 1000000L + (tv2.tv_usec - tv1.tv_usec);
  printf ("Elapsed time = %d usec\n", diff);

  printf ("Sum = %ld\n", sum);

  return 0;

}

The final result is :

Elapsed time = 232869 usec
Sum = 100000000

Unlike the first syntax, I don't need in this second version to declare the sum and n variables outside the int main() function.

Moreover, I need to escape all the '%' symbols with another '% : this is not the case for the first syntax.

Except these little differences, could we say these 2 syntaxes are equivalent for inserting SPARC inline Assembly into C code ?

Thanks for your remarks, regards.

Community
  • 1
  • 1
  • The second one is better because it interoperates with the compiler better. Also, for the first one, you have to be very careful about which registers you may modify. Just because it works for one case, it may suddenly and mysteriously break under other circumstances. Unfortunately that applies to the second version too, if you get the constraints wrong ;) – Jester May 22 '17 at 00:19
  • Thanks, it seems the first syntax is more readable but it is more error prone than the second one. –  May 22 '17 at 00:26
  • I'd strengthen @jester's answer by saying that the first way is terrible and works only by luck. Since the used registers are not declared in the clobber list, the compiler is free to use them, and the code is technically incorrect. And it's not more readable. The second bit of code is better since the one register used, %g1, is declared as being clobbered, so it will always work. – Rob Gardner May 22 '17 at 00:29

0 Answers0