title: inline asm with sideeffects
body: <p>I want to use inline asm for ARMv7 with clang 3.4, in order to write low level code that accesses the CPUs control registers.  As a test, I wrote a program that reads from a register, conditionally fiddles with some bits, and writes back the new value.</p>
  
  <p>However, when I look at the produced machine code the entire bit-fiddling has been optimized away.  Apparently I have not used the right asm constraints to tell clang that the result of writing to the register depends on what is being written. (I only used a simple "volatile" modifier).</p>
  
  <p>How should I write the inline asm code so that clang generates correct asm?  Here is the code <code>test.c</code></p>
  
  <pre><code>typedef unsigned int uint32_t;
  
  // code that reads and writes the ID_PFR1 register
  
  uint32_t read_ID_PFR1() {
    uint32_t a;
    asm volatile ("mrc     p15, 0, %0, c0, c1, 1" : : "r"(a) : );
    return a;
  }
  
  void write_ID_PFR1(uint32_t a) {
    asm volatile ("mcr     p15, 0, %0, c0, c1, 1" :"=r"(a) :  :  );
  }
  
  // regular c code that modifies the register
  
  uint32_t foo(uint32_t b) {
    uint32_t a;
    a = read_ID_PFR1();
    write_ID_PFR1(b);
    return a+b;
  }
  
  void bit_fiddle() {
    uint32_t a;
    a = read_ID_PFR1();
    if ((a &amp; 0x3) == 1) {
      a |= 1&lt;&lt;2;
    }
    a |= 1&lt;&lt;3;
    write_ID_PFR1(a);
  }
  </code></pre>
  
  <p>I compiled it with </p>
  
  <pre><code>clang-3.4 -target armv7a-none-eabi test.c -o test -O3
  </code></pre>
  
  <p>This is the resulting machine code</p>
  
  <pre><code>$ arm-linux-gnueabi-objdump -S test
  
  test:     file format elf32-littlearm
  
  
  Disassembly of section .text:
  
  00000000 &lt;read_ID_PFR1&gt;:
     0:   ee100f31    mrc 15, 0, r0, cr0, cr1, {1}
     4:   e12fff1e    bx  lr
  
  00000008 &lt;write_ID_PFR1&gt;:
     8:   ee000f31    mcr 15, 0, r0, cr0, cr1, {1}
     c:   e12fff1e    bx  lr
  
  00000010 &lt;foo&gt;:
    10:   ee100f31    mrc 15, 0, r0, cr0, cr1, {1}
    14:   ee000f31    mcr 15, 0, r0, cr0, cr1, {1}
    18:   e12fff1e    bx  lr
  
  0000001c &lt;bit_fiddle&gt;:
    1c:   ee100f31    mrc 15, 0, r0, cr0, cr1, {1}
    20:   ee000f31    mcr 15, 0, r0, cr0, cr1, {1}
    24:   e12fff1e    bx  lr
  </code></pre>
  
  <p>As you can see in <code>&lt;bit_fiddle&gt;</code>, nothing is left between the <code>mrc</code> and <code>mcr</code> instructions.  And also see how <code>foo</code> fails to add together <code>a+b</code> in the produced machine code.</p>