Prevent compiler from reordering inline assembly

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
ers35
Active Member
Posts: 62
Joined: Mon Jun 10, 2013 2:14 pm

Prevent compiler from reordering inline assembly

Post by ers35 »

I want to do a partial timed input on multiple buffered ports in XC.
XC does not have partin_timed, so I must use inline assembly.
However, the compiler reorders the inline assembly and the behavior of the code changes completely.

I want to guarantee that the four inline assembly instructions appear in the
same order once compiled:

Code: Select all

u16 t;
u32 sample[1];
while (1)
{
  wordclock when pinseq(0) :> void;
  wordclock when pinseq(1) :> void @ t;
  asm volatile ("setpt res[%0], %1" :: "r"(din[0]), "r"(t + 23));
  asm volatile ("setpt res[%0], %1" :: "r"(dout[0]), "r"(t + 32));
  asm volatile ("outpw res[%0], %1, 24" :: "r"(dout[0]), "r"(sample[0]));
  asm volatile ("inpw %0, res[%1], 24" : "=r"(sample[0]) : "r"(din[0]));
  
  asm volatile ("setpt res[%0], %1" :: "r"(din[0]), "r"(t + 55));
  asm volatile ("setpt res[%0], %1" :: "r"(dout[0]), "r"(t + 64));
  asm volatile ("outpw res[%0], %1, 24" :: "r"(dout[0]), "r"(sample[0]));
  asm volatile ("inpw %0, res[%1], 24" : "=r"(sample[0]) : "r"(din[0]));
}
This is the order once compiled:

Code: Select all

setpt
setpt
outpw
setpt
setpt
inpw
outpw
inpw
This works, but is complicated and will get even more complicated when I add the other
ports.

Code: Select all

asm volatile
(
  "setpt res[%1], %3\n\t"
  "setpt res[%2], %4\n\t"
  "outpw res[%2], %5, 24\n\t"
  "inpw %0, res[%1], 24\n\t"
  // outputs
  :
  // %0
  "=r"(sample[0])
  // inputs
  :
  // %1        %2            %3           %4           %5
  "r"(din[0]), "r"(dout[0]), "r"(t + 23), "r"(t + 32), "r"(sample[0])
);
I could write the whole thing in assembly, but is there any other option?


User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

The best solution is to write a single asm, or to write your
whole function as assembler. But you don't want that :-)

To keep the compiler from reordering two asm statements,
make sure there is a dependency between them. For example:

Code: Select all

int junk;
asm("blabla %1,%2" : "=r"(junk) : "r"(a), "r"(b));
asm("blabla %1,%2" : "+r"(junk) : "r"(c), "r"(d));
asm("blabla %1,%2" : : "r"(junk), "r"(e), "r"(f));
richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

ers35 wrote:I want to do a partial timed input on multiple buffered ports in XC.
XC does not have partin_timed, so I must use inline assembly.
However, the compiler reorders the inline assembly and the behavior of the code changes completely.

I want to guarantee that the four inline assembly instructions appear in the
same order once compiled
Marking the asm as volatile should be sufficient - it indicates that the asm has side-effects and the compiler shouldn't motion operations with unmodelled side-effects across each other. I tried to turn you code snippet into a standalone example:

Code: Select all

#include <xs1.h>
#include <stdint.h>

typedef uint16_t u16;
typedef uint32_t u32;

void f(port wordclock, port din[1], port dout[1])
{
  u16 t;
  u32 sample[1];
  while (1)
  {
    wordclock when pinseq(0) :> void;
    wordclock when pinseq(1) :> void @ t;
    asm volatile ("setpt res[%0], %1" :: "r"(din[0]), "r"(t + 23));
    asm volatile ("setpt res[%0], %1" :: "r"(dout[0]), "r"(t + 32));
    asm volatile ("outpw res[%0], %1, 24" :: "r"(dout[0]), "r"(sample[0]));
    asm volatile ("inpw %0, res[%1], 24" : "=r"(sample[0]) : "r"(din[0]));
   
    asm volatile ("setpt res[%0], %1" :: "r"(din[0]), "r"(t + 55));
    asm volatile ("setpt res[%0], %1" :: "r"(dout[0]), "r"(t + 64));
    asm volatile ("outpw res[%0], %1, 24" :: "r"(dout[0]), "r"(sample[0]));
    asm volatile ("inpw %0, res[%1], 24" : "=r"(sample[0]) : "r"(din[0]));
  }
}
However if I compile the above example there is no reordering (as I would expect). What tools version are you using? Are you able to create a simple testcase?
User avatar
ers35
Active Member
Posts: 62
Joined: Mon Jun 10, 2013 2:14 pm

Post by ers35 »

I found the problem. I had

Code: Select all

#define volatile
in a header file. That removed the volatile from the inline assembly, which is why the compiler reordered it.
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

Ha, that would do it :-)