<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - Extended asm %Qx/%Rx are backwards on big-endian ARMv7"
   href="https://llvm.org/bugs/show_bug.cgi?id=23297">23297</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Extended asm %Qx/%Rx are backwards on big-endian ARMv7
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>3.5
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>Other
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>other
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Driver
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>solra@bizna.name
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>This bug revolves around an obscure case in a compatible reimplementation of an
essentially undocumented aspect of a GCC extension. Here goes.

Example code: (compile with "-O3 -target armv7a-eabi" and either
"-mlittle-endian" or "-mbig-endian")

#include <stdio.h>
void test() {
  long long var;
  asm("MRRC p3, 0, %Q0, %R0, cr0":"=r"(var):);
  var = var + 1;
  printf("%016llX\n", var);
}

In GCC's extended asm for ARM targets, Q and R indicate, respectively, the
least significant and most significant register of a register pair. The given
example is a transfer from a 64-bit coprocessor register (cr0 of coprocessor
#3) to two core registers (the low-order half and the high-order half of
"var").

Regardless of whether I compile with -mlittle-endian or -mbig-endian, r0 is
given as the low register and r1 as the high register:

   8:   ec510300        mrrc    3, 0, r0, r1, cr0

But the following two instructions demonstrate that this order is incorrect on
big-endian:

Little-endian: (r0 is low, r1 is high)
   c:   e2902001        adds    r2, r0, #1
  10:   e2a13000        adc     r3, r1, #0
Big-endian: (r0 is high, r1 is low)
   c:   e2913001        adds    r3, r1, #1
  10:   e2a02000        adc     r2, r0, #0

GCC 4.6, on the other hand, handles this correctly:

Little-endian:
   8:   ec532300        mrrc    3, 0, r2, r3, cr0
Big-endian:
   8:   ec523300        mrrc    3, 0, r3, r2, cr0

Unrelatedly, it is interesting to compare GCC's optimization of this function
to Clang's... GCC saves, uses, and restores some wholly unnecessary scratch
registers, but also performs a tail call optimization, which Clang doesn't (and
can't, since it saves the frame pointer while GCC doesn't).</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>