ftp.nice.ch/pub/next/developer/languages/c/djgpp-NS.s.tar.gz#/djgpp/include/sys/farptr.h

This is farptr.h in view mode; [Download] [Up]

/* Copyright (c) 1994 DJ Delorie.  Donated to the public domain.

   THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
   IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
º		Far Pointer Simulation Functions			º
ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

This file attempts to make up for the lack of a "far" keyword in GCC. 
Although it doesn't provide access to far call APIs (like Windows), it
does allow you to do far pointer data access without the overhead of
movedata() or dosmemget/dosmemput().

You should *always* include this file when using these functions and
compile with optimization enabled.  They don't exist as normal functions
in any library, and they compile down to only a few opcodes when used
this way.  They are almost as fast as native pointer operations, and
about as fast as far pointers can get. 

If you don't use optimization, this file becomes prototypes for
farptr.c, which generates real functions for these when not optimizing. 
When optimizing, farptr.c compiles to nothing. 

There are two types of functions here - standalone and invariant.  The
standalone functions take a selector and offset.  These are used when
you need only a few accesses, time isn't critical, or you don't know
what's in the %fs register.  The invariant ones don't take a selector,
they only take an offset.  These are used inside loops and in
time-critical accesses where the selector doesn't change.  To specify
the selector, use the farsetsel() function.  That selector is used for
all farns*() functions until changed. 

The farpoke* and farpeek* take selectors.

The farnspoke* and farnspeek* don't (note the `ns' for `no selector').

Warning: These routines all use the %fs register for their accesses. 
GCC normally uses only %ds and %es, and libc functions (movedata,
dosmemget, dosmemput) use %gs.  Still, you should be careful about
assumptions concerning whether or not the value you put in %fs will be
preserved across calls to other functions.  If you guess wrong, your
program will crash.  Better safe than sorry. 

Note: There are two places where asm constraints are casted.  One
(farpokeb) is because signed char won't fit in unsigned char's range
when arguments are constants, the other (farpeekb) gets compiled to (for
example) %eax, but gas puts in opcodes for (for example) %al instead. 
Both are workarounds for errors that gcc emits (but I don't know why). 

*/

#ifndef _FAR_POINTER_H_
#define _FAR_POINTER_H_

extern inline void
_farpokeb(unsigned short selector,
	 unsigned long offset,
	 unsigned char value)
{
  asm("movw %0,%%fs"
      :
      : "r" (selector));
  asm(".byte 0x64\n"
      "	movb %0,(%1)"
      :
      : "r" ((unsigned char)value), "r" (offset));
}

extern inline void
_farpokew(unsigned short selector,
	 unsigned long offset,
	 unsigned short value)
{
  asm("movw %0,%%fs"
      :
      : "r" (selector));
  asm(".byte 0x64\n"
      "	movw %0,(%1)"
      :
      : "r" (value), "r" (offset));
}

extern inline void
_farpokel(unsigned short selector,
	 unsigned long offset,
	 unsigned long value)
{
  asm("movw %0,%%fs"
      :
      : "r" (selector));
  asm(".byte 0x64\n"
      "	movl %0,(%1)"
      :
      : "r" (value), "r" (offset));
}

extern inline unsigned char
_farpeekb(unsigned short selector,
	 unsigned long offset)
{
  unsigned char result;
  asm("movw %0,%%fs"
      :
      : "r" (selector));
  asm(".byte 0x64\n"
      "	movb (%1),%0"
      : "=r" ((int)result)
      : "r" (offset));
  return result;
}

extern inline unsigned short
_farpeekw(unsigned short selector,
	 unsigned long offset)
{
  unsigned short result;
  asm("movw %0,%%fs"
      :
      : "r" (selector));
  asm(".byte 0x64\n"
      "	movw (%1),%0"
      : "=r" (result)
      : "r" (offset));
  return result;
}

extern inline unsigned long
_farpeekl(unsigned short selector,
	 unsigned long offset)
{
  unsigned long result;
  asm("movw %0,%%fs"
      :
      : "r" (selector));
  asm(".byte 0x64\n"
      "	movl (%1),%0"
      : "=r" (result)
      : "r" (offset));
  return result;
}

extern inline void
_farsetsel(unsigned short selector)
{
  asm("movw %0,%%fs"
      :
      : "r" (selector));
}

extern inline unsigned char
_farnspokeb(unsigned long offset,
	 unsigned char value)
{
  asm(".byte 0x64\n"
      "	movb %0,(%1)"
      :
      : "r" (value), "r" (offset));
}

extern inline unsigned char
_farnspokew(unsigned long offset,
	 unsigned short value)
{
  asm(".byte 0x64\n"
      "	movw %0,(%1)"
      :
      : "r" (value), "r" (offset));
}

extern inline unsigned char
_farnspokel(unsigned long offset,
	 unsigned long value)
{
  asm(".byte 0x64\n"
      "	movl %0,(%1)"
      :
      : "r" (value), "r" (offset));
}

extern inline unsigned char
_farnspeekb(unsigned long offset)
{
  unsigned char result;
  asm(".byte 0x64\n"
      "	movb (%1),%0"
      : "=r" (result)
      : "r" (offset));
  return result;
}

extern inline unsigned short
_farnspeekw(unsigned long offset)
{
  unsigned short result;
  asm(".byte 0x64\n"
      "	movw (%1),%0"
      : "=r" (result)
      : "r" (offset));
  return result;
}

extern inline unsigned long
_farnspeekl(unsigned long offset)
{
  unsigned long result;
  asm(".byte 0x64\n"
      "	movl (%1),%0"
      : "=r" (result)
      : "r" (offset));
  return result;
}

#endif /* _FAR_POINTER_H_ */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.