On Sunday, 17 August 2014 at 11:35:33 UTC, Artur Skawina via
D.gnu wrote:
It works for me:
import volat; // module w/ the last Volatile(T)
implementation.
struct uartreg {
Volatile!int sr;
Volatile!int dr;
Volatile!int brr;
Volatile!int cr1;
Volatile!int cr2;
Volatile!int cr3;
Volatile!int gtpr;
// send a byte to the uart
void send(int t) {
while ((sr&0x80)==0)
{ }
dr=t;
}
}
enum uart = cast(uartreg*)0xDEADBEAF;
void main() {
uart.send(42);
}
=>
0000000000403620 <_Dmain>:
403620: b8 af be ad de mov $0xdeadbeaf,%eax
403625: 0f 1f 00 nopl (%rax)
403628: b9 af be ad de mov $0xdeadbeaf,%ecx
40362d: 8b 11 mov (%rcx),%edx
40362f: 81 e2 80 00 00 00 and $0x80,%edx
403635: 74 f1 je 403628
<_Dmain+0x8>
403637: bf b3 be ad de mov $0xdeadbeb3,%edi
40363c: 31 c0 xor %eax,%eax
40363e: c7 07 2a 00 00 00 movl $0x2a,(%rdi)
403644: c3 retq
Except for some obviously missed optimizations (dead eax load,
unnecessary ecx reload), the code seems fine. What platform
are you using and what does the emitted code look like?
Also if I have:
cr1=cr2=0;
I get: expression this.cr2.opAssign(0) is void and has no value
That's because the opAssign returns void, which prevents this
kind of chaining. This was a deliberate choice, as I /wanted/ to
disallow that; it's already a bad idea for normal assignments;
for volatile ones, which can require a specific order, it's an
even worse one.
But it's trivial to "fix", just change
void opAssign(A)(A a) { volatile_store(raw, a); }
to
T opAssign(A)(A a) { volatile_store(raw, a); return a; }
artur
I am compiling for arm and I am sorry I misinterpreted the
optimized code. Actually the code is correct but it still does
not work.
The problem is that the call to get the tls pointer for
volatile_dummy seems to corrupt the register (r3) where the this
pointer is. The call is inside the while loop. After removing
tha call by hand in the assembly everything works. R3 is usually
pushed into stack when it is used in a function. I have to check
what is wrong in this case.