Hi everyone, I am looking for some clarification about how are working the memory operands, especially when the constraint allows memory only (eg. "m"). Please note that in a lesser extent, I know (by looking the gcc sources) how the things are currently working but I wonder if it is a design choice or simply a serendipitous engineering consequence. Indeed, as far as I know, the documentation is not explicit on this.
Only things related to memory I have found are: > A string constant specifying constraints on the placement of the operand; See > Constraints, for details. > ‘ m ’ A memory operand is allowed, with any kind of address that the machine > supports in general. When I read this, I think that "m" work exactly as "r" from a C point of view. But in fact, there are some conceptual corner cases where there are not equivalent. (1) It is said that an output must be an lvalue. However, it is said nowhere (except that compilation fails) that if the constraint allows only memory, an input expression must be an lvalue too. There are a lot of workarounds, but why the following code (actually not relevant) is rejected? __asm__ ("movl %1, %0" : "=r" (x) : "m" (1)); I would think that the compiler could put the constant 1 in the stack or in a static address or even reuse any memory address known to hold the value 1. (2) If the constraint allows only memory, does the compiler allowed to make a copy? (if no, why?) (2.1) Thus, if I declare an output and an input using the same lvalue, am I guaranteed that they both point to the same location? (as far as I know, it is not true for register constraint) __asm__ ("incl %0" : "=m" (x) : "m" (x)); (2.2) Moreover, in the following example of the doc, is edi guaranteed to point to the memory pointed by "m" (*(const char (*)[]) p) ? > asm("repne scasb" > : "=c" (count), "+D" (p) > : "m" (*(const char (*)[]) p), "0" (-1), "a" (0)); I had a hard time to figure out why it is actually working -- partially explaining the (1). In fact, from a C perspective, *(const char (*)[]) evaluates to a (const char *), so I would think: place the value of p in an arbitrary memory location. (Note that it is what is happening when the constraint also allows a register, but no register is free) (2.3) Would it make sense to use early clobber '&' to force two memory locations to be distinct? char t[4] = "abcd"; int x = 0x64636261; __asm__ ("..." : "+&m" (t) : "m" (x)); From a low-level optimizer perspective, both t and x have the same value so it would be interesting to pass the same memory location if the first one was not early clobber. (3) I understand that writing a "phantom" entry like in (2.2) make possible to avoid the use of the "memory" keyword. Would it make it simpler if there is a dedicated syntax to state that memory from an input pointer is accessed? For instance, something like: __asm__ ("repne scasb" : "=c" (count), "+D" (p) : "0" (-1), "a" (0) : "memory(1)"); or __asm__ ("repne scasb" : "=c" (count), [P] "+D" (p) : "0" (-1), "a" (0) : "@[P]"); Regards, Frédéric Recoules