On Tue, Mar 27, 2012 at 10:53 AM, Uros Bizjak <ubiz...@gmail.com> wrote: > On Tue, Mar 27, 2012 at 7:28 PM, H.J. Lu <hjl.to...@gmail.com> wrote: > >> GCC needs to move the value in the %fs segment >> register into %r32 or %r64. This instruction >> >> "mov{l}\t{%%fs:0, %k0|%k0, DWORD PTR fs:0}" >> >> does exactly what GCC wants. > > Sorry, I really don't understand what you are trying to say. > > You are loading ptrmode (so, void *) pointer from %fs:0 to a DImode > register. If you use movl, you can say that this instruction zero > extends the value (void *, ptrmode, SImode) from a memory location > pointed by %fs:0 to a DImode register. Please note the difference > between: > > movl %fs:0, %eax > > and > > movl %fs, %eax. > > BTW: %fs is a 16bit register. >
%fs and %gs are special in 64bit mode. For a memory operand "%fs:address", its effective address is base address of %fs + address. The base address of %fs and %fs are hidden. "mov %fs, %eax" will only access the visible part of %fs, which is the 16bit segment selector. In 64bit mode, UNSPEC_TP is the base address of %fs. To access the base address of %fs, we can use system call: int arch_prctl(int code, unsigned long addr); int arch_prctl(int code, unsigned long *addr); ARCH_SET_FS Set the 64-bit base for the FS register to addr. ARCH_GET_FS Return the 64-bit base value for the FS register of the current thread in the unsigned long pointed to by addr. BTW, 4 new instructions are added to read/write base address of %fs/%gs directly. For now, we have to use the system call to update base address of %fs, To read the base address of %fs, OS arranges that the base address of %fs points to a struct: typedef struct { void *tcb; /* Pointer to the TCB. Not necessarily the thread descriptor used by libpthread. */ ... } and sets up tcb == the base address of %fs. Then we can use "mov{l}\t{%%fs:0, %k0|%k0, DWORD PTR fs:0}" to move the base address of %fs into %r32 and %r64 directly. I hope this answers your questions. Thanks. -- H.J.