On Tue, Mar 20, 2012 at 11:43 AM, Uros Bizjak <ubiz...@gmail.com> wrote: > On Tue, Mar 20, 2012 at 7:27 PM, H.J. Lu <hjl.to...@gmail.com> wrote: > >>>> I think use the OS provided instruction to load TP into DImode register >>>> could simplify the code. >>> >>> Which OS provided instruction? >>> >>> Please see how TP is defined in get_thread_pointer, it is in ptr_mode: >>> >>> rtx tp = gen_rtx_UNSPEC (ptr_mode, gen_rtvec (1, const0_rtx), UNSPEC_TP); >>> >>> This says that TP is in SImode on X32. > >> TP is defined as (unspec:DI [(const_int 0]) UNSPEC_TP) >> and provided by OS. It is a CONST_INT, but its value is opaque >> to GCC. MODE here has no impact on its value provided by OS. >> X32 OS provides instructions to load TP to into an SImode and >> DImode registers. > > You must be looking to some other GCC sources than me. > > (define_insn "*load_tp_x32" > [(set (match_operand:SI 0 "register_operand" "=r") > (unspec:SI [(const_int 0)] UNSPEC_TP))] > "TARGET_X32" > "mov{l}\t{%%fs:0, %0|%0, DWORD PTR fs:0}" > [(set_attr "type" "imov") > (set_attr "modrm" "0") > (set_attr "length" "7") > (set_attr "memory" "load") > (set_attr "imm_disp" "false")]) > > (define_insn "*load_tp_x32_zext" > [(set (match_operand:DI 0 "register_operand" "=r") > (zero_extend:DI (unspec:SI [(const_int 0)] UNSPEC_TP)))] > "TARGET_X32" > "mov{l}\t{%%fs:0, %k0|%k0, DWORD PTR fs:0}" > [(set_attr "type" "imov") > (set_attr "modrm" "0") > (set_attr "length" "7") > (set_attr "memory" "load") > (set_attr "imm_disp" "false")]) >
Thread pointer (TP) points to thread control block (TCB). X32 TCB is typedef struct { void *tcb; /* Pointer to the TCB. Not necessarily the thread descriptor used by libpthread. */ ... } It is a 32bit address set up by OS. That is where 0 in "%fs:0" comes from since it is the first field of the struct %fs points to. X32 OS provides mov %fs:0, %eax to load the address of TCB into EAX and mov %fs:0, %eax to load the address of TCB into RAX since OS guarantees that the upper 32bits of the address of TCB are all 0s. We added "*load_tp_x32_zext" since we zero-extend SI TP to DI TP. Or we can use mov %fs:0, %eax to directly load the value of the tcb field into RAX and remove "*load_tp_x32_zext". It will simplify the code. -- H.J.