4 staticinlineunsigned charget_user_byte(const char* addr
) 6 registerunsigned char _v
; 8 __asm__("movb %%fs:%1,%0":"=q"(_v
):"m"(*addr
)); 12 #define get_fs_byte(addr) get_user_byte((char *)(addr)) 14 staticinlineunsigned shortget_user_word(const short*addr
) 18 __asm__("movw %%fs:%1,%0":"=r"(_v
):"m"(*addr
)); 22 #define get_fs_word(addr) get_user_word((short *)(addr)) 24 staticinlineunsigned longget_user_long(const int*addr
) 28 __asm__("movl %%fs:%1,%0":"=r"(_v
):"m"(*addr
)); \
32 #define get_fs_long(addr) get_user_long((int *)(addr)) 34 staticinlinevoidput_user_byte(char val
,char*addr
) 36 __asm__("movb %0,%%fs:%1":/* no outputs */:"iq"(val
),"m"(*addr
)); 39 #define put_fs_byte(x,addr) put_user_byte((x),(char *)(addr)) 41 staticinlinevoidput_user_word(short val
,short* addr
) 43 __asm__("movw %0,%%fs:%1":/* no outputs */:"ir"(val
),"m"(*addr
)); 46 #define put_fs_word(x,addr) put_user_word((x),(short *)(addr)) 48 staticinlinevoidput_user_long(unsigned long val
,int* addr
) 50 __asm__("movl %0,%%fs:%1":/* no outputs */:"ir"(val
),"m"(*addr
)); 53 #define put_fs_long(x,addr) put_user_long((x),(int *)(addr)) 55 staticinlinevoid__generic_memcpy_tofs(void* to
,const void* from
,unsigned long n
) 64 "1:\ttestb $2,%%cl\n\t" 67 "2:\tshrl $2,%%ecx\n\t" 71 :"c"(n
),"D"((long) to
),"S"((long) from
) 75 staticinlinevoid__constant_memcpy_tofs(void* to
,const void* from
,unsigned long n
) 81 put_user_byte(*(const char*) from
, (char*) to
); 84 put_user_word(*(const short*) from
, (short*) to
); 87 put_user_word(*(const short*) from
, (short*) to
); 88 put_user_byte(*(2+(const char*) from
),2+(char*) to
); 91 put_user_long(*(const int*) from
, (int*) to
); 103 :"c" (n/4),"D" ((long) to),"S" ((long) from) \ 117 COMMON("movsw\n\tmovsb\n\t"); 123 staticinlinevoid__generic_memcpy_fromfs(void* to
,const void* from
,unsigned long n
) 129 "1:\ttestb $2,%%cl\n\t" 132 "2:\tshrl $2,%%ecx\n\t" 135 :"c"(n
),"D"((long) to
),"S"((long) from
) 136 :"cx","di","si","memory"); 139 staticinlinevoid__constant_memcpy_fromfs(void* to
,const void* from
,unsigned long n
) 145 *(char*)to
=get_user_byte((const char*) from
); 148 *(short*)to
=get_user_word((const short*) from
); 151 *(short*) to
=get_user_word((const short*) from
); 152 *(char*) to
=get_user_byte(2+(const char*) from
); 155 *(int*) to
=get_user_long((const int*) from
); 160 "rep ; fs ; movsl\n\t" \ 163 :"c" (n/4),"D" ((long) to),"S" ((long) from) \ 164 :"cx","di","si","memory") 171 COMMON("fs ; movsb"); 174 COMMON("fs ; movsw"); 177 COMMON("fs ; movsw\n\tfs ; movsb"); 183 #define memcpy_fromfs(to, from, n) \ 184 (__builtin_constant_p(n) ? \ 185 __constant_memcpy_fromfs((to),(from),(n)) : \ 186 __generic_memcpy_fromfs((to),(from),(n))) 188 #define memcpy_tofs(to, from, n) \ 189 (__builtin_constant_p(n) ? \ 190 __constant_memcpy_tofs((to),(from),(n)) : \ 191 __generic_memcpy_tofs((to),(from),(n))) 194 * Someone who knows GNU asm better than I should double check the following. 195 * It seems to work, but I don't know if I'm doing something subtly wrong. 197 * [ nothing wrong here, Linus: I just changed the ax to be any reg ] 200 staticinlineunsigned longget_fs(void) 203 __asm__("mov %%fs,%w0":"=r"(_v
):"0"(0)); 207 staticinlineunsigned longget_ds(void) 210 __asm__("mov %%ds,%w0":"=r"(_v
):"0"(0)); 214 staticinlinevoidset_fs(unsigned long val
) 216 __asm__
__volatile__("mov %w0,%%fs":/* no output */:"r"(val
)); 219 #endif/* _ASM_SEGMENT_H */