//// ȡfs ַָֽڡ
// addr - ָڴַ
// %0 - (صֽ_v)%1 - (ڴַaddr)
// أڴfs:[addr]ֽڡ
extern inline unsigned char
get_fs_byte (const char *addr)
{
  unsigned register char _v;

__asm__ ("movb %%fs:%1,%0": "=r" (_v):"m" (*addr));
  return _v;
}

//// ȡfs ַָ֡
// addr - ָڴַ
// %0 - (ص_v)%1 - (ڴַaddr)
// أڴfs:[addr]֡
extern inline unsigned short
get_fs_word (const unsigned short *addr)
{
  unsigned short _v;

__asm__ ("movw %%fs:%1,%0": "=r" (_v):"m" (*addr));
  return _v;
}

//// ȡfs ַָĳ(4 ֽ)
// addr - ָڴַ
// %0 - (صĳ_v)%1 - (ڴַaddr)
// أڴfs:[addr]ĳ֡
extern inline unsigned long
get_fs_long (const unsigned long *addr)
{
  unsigned long _v;

__asm__ ("movl %%fs:%1,%0": "=r" (_v):"m" (*addr));
  return _v;
}

//// һֽڴfs ָڴַ
// val - ֵֽaddr - ڴַ
// %0 - Ĵ(ֵֽval)%1 - (ڴַaddr)
extern inline void
put_fs_byte (char val, char *addr)
{
  __asm__ ("movb %0,%%fs:%1"::"r" (val), "m" (*addr));
}

//// һִfs ָڴַ
// val - ֵaddr - ڴַ
// %0 - Ĵ(ֵval)%1 - (ڴַaddr)
extern inline void
put_fs_word (short val, short *addr)
{
  __asm__ ("movw %0,%%fs:%1"::"r" (val), "m" (*addr));
}

//// һִfs ָڴַ
// val - ֵaddr - ڴַ
// %0 - Ĵ(ֵval)%1 - (ڴַaddr)
extern inline void
put_fs_long (unsigned long val, unsigned long *addr)
{
  __asm__ ("movl %0,%%fs:%1"::"r" (val), "m" (*addr));
}

/*
* Someone who knows GNU asm better than I should double check the followig.
* It seems to work, but I don't know if I'm doing something subtly wrong.
* --- TYT, 11/24/91
* [ nothing wrong here, Linus ]
*/
/*
* ҸGNU ӦϸĴ롣ЩʹãҲ֪Ƿ
* һЩС
* --- TYT1991 11 24 
* [ ЩûдLinus ]
*/

//// ȡfs μĴֵ(ѡ)
// أfs μĴֵ
extern inline unsigned long
get_fs ()
{
  unsigned short _v;
__asm__ ("mov %%fs,%%ax": "=a" (_v):);
  return _v;
}

//// ȡds μĴֵ
// أds μĴֵ
extern inline unsigned long
get_ds ()
{
  unsigned short _v;
__asm__ ("mov %%ds,%%ax": "=a" (_v):);
  return _v;
}

//// fs μĴ
// val - ֵѡ
extern inline void
set_fs (unsigned long val)
{
  __asm__ ("mov %0,%%fs"::"a" ((unsigned short) val));
}
