0,0 → 1,249 |
/* special version for libc - uses %gs instead of %fs. Ignore comments */ |
|
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ |
/* Copyright (c) 1995 DJ Delorie. Permission granted to use for any |
purpose, provided this copyright remains attached and unmodified. |
|
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 %gs 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. You can use _fargetsel() if you |
want to temporary change the selector with _farsetsel() and restore |
it afterwards. |
|
The farpoke* and farpeek* take selectors. |
|
The farnspoke* and farnspeek* don't (note the `ns' for `no selector'). |
|
Warning: These routines all use the %gs 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 %gs will be |
preserved across calls to other functions. If you guess wrong, your |
program will crash. Better safe than sorry. |
|
*/ |
|
#ifndef __dj_include_sys_farptr_h_ |
#define __dj_include_sys_farptr_h_ |
|
#ifdef __cplusplus |
extern "C" { |
#endif |
|
#ifndef __dj_ENFORCE_ANSI_FREESTANDING |
|
#ifndef __STRICT_ANSI__ |
|
#ifndef _POSIX_SOURCE |
|
void _farpokeb(unsigned short, unsigned long, unsigned char); |
void _farpokew(unsigned short, unsigned long, unsigned short); |
void _farpokel(unsigned short, unsigned long, unsigned long); |
unsigned char _farpeekb(unsigned short, unsigned long); |
unsigned short _farpeekw(unsigned short, unsigned long); |
unsigned long _farpeekl(unsigned short, unsigned long); |
void _farsetsel(unsigned short); |
unsigned short _fargetsel(void); |
void _farnspokeb(unsigned long, unsigned char); |
void _farnspokew(unsigned long, unsigned short); |
void _farnspokel(unsigned long, unsigned long); |
unsigned char _farnspeekb(unsigned long); |
unsigned short _farnspeekw(unsigned long); |
unsigned long _farnspeekl(unsigned long); |
|
extern __inline__ void |
_farpokeb(unsigned short selector, |
unsigned long offset, |
unsigned char value) |
{ |
__asm__ __volatile__ ("movw %w0,%%gs\n" |
" .byte 0x65 \n" |
" movb %b1,(%k2)" |
: |
: "rm" (selector), "qi" (value), "r" (offset)); |
} |
|
extern __inline__ void |
_farpokew(unsigned short selector, |
unsigned long offset, |
unsigned short value) |
{ |
__asm__ __volatile__ ("movw %w0,%%gs \n" |
" .byte 0x65 \n" |
" movw %w1,(%k2)" |
: |
: "rm" (selector), "ri" (value), "r" (offset)); |
} |
|
extern __inline__ void |
_farpokel(unsigned short selector, |
unsigned long offset, |
unsigned long value) |
{ |
__asm__ __volatile__ ("movw %w0,%%gs \n" |
" .byte 0x65 \n" |
" movl %k1,(%k2)" |
: |
: "rm" (selector), "ri" (value), "r" (offset)); |
} |
|
extern __inline__ unsigned char |
_farpeekb(unsigned short selector, |
unsigned long offset) |
{ |
unsigned char result; |
__asm__ __volatile__ ("movw %w1,%%gs \n" |
" .byte 0x65 \n" |
" movb (%k2),%b0" |
: "=q" (result) |
: "rm" (selector), "r" (offset)); |
return result; |
} |
|
extern __inline__ unsigned short |
_farpeekw(unsigned short selector, |
unsigned long offset) |
{ |
unsigned short result; |
__asm__ __volatile__ ("movw %w1, %%gs \n" |
" .byte 0x65 \n" |
" movw (%k2),%w0 \n" |
: "=r" (result) |
: "rm" (selector), "r" (offset)); |
return result; |
} |
|
extern __inline__ unsigned long |
_farpeekl(unsigned short selector, |
unsigned long offset) |
{ |
unsigned long result; |
__asm__ __volatile__ ("movw %w1,%%gs\n" |
" .byte 0x65\n" |
" movl (%k2),%k0" |
: "=r" (result) |
: "rm" (selector), "r" (offset)); |
return result; |
} |
|
extern __inline__ void |
_farsetsel(unsigned short selector) |
{ |
__asm__ __volatile__ ("movw %w0,%%gs" |
: |
: "rm" (selector)); |
} |
|
extern __inline__ unsigned short |
_fargetsel(void) |
{ |
unsigned short selector; |
__asm__ __volatile__ ("movw %%gs,%w0 \n" |
: "=r" (selector) |
: ); |
return selector; |
} |
|
extern __inline__ void |
_farnspokeb(unsigned long offset, |
unsigned char value) |
{ |
__asm__ __volatile__ (".byte 0x65\n" |
" movb %b0,(%k1)" |
: |
: "qi" (value), "r" (offset)); |
} |
|
extern __inline__ void |
_farnspokew(unsigned long offset, |
unsigned short value) |
{ |
__asm__ __volatile__ (".byte 0x65\n" |
" movw %w0,(%k1)" |
: |
: "ri" (value), "r" (offset)); |
} |
|
extern __inline__ void |
_farnspokel(unsigned long offset, |
unsigned long value) |
{ |
__asm__ __volatile__ (".byte 0x65\n" |
" movl %k0,(%k1)" |
: |
: "ri" (value), "r" (offset)); |
} |
|
extern __inline__ unsigned char |
_farnspeekb(unsigned long offset) |
{ |
unsigned char result; |
__asm__ __volatile__ (".byte 0x65\n" |
" movb (%k1),%b0" |
: "=q" (result) |
: "r" (offset)); |
return result; |
} |
|
extern __inline__ unsigned short |
_farnspeekw(unsigned long offset) |
{ |
unsigned short result; |
__asm__ __volatile__ (".byte 0x65\n" |
" movw (%k1),%w0" |
: "=r" (result) |
: "r" (offset)); |
return result; |
} |
|
extern __inline__ unsigned long |
_farnspeekl(unsigned long offset) |
{ |
unsigned long result; |
__asm__ __volatile__ (".byte 0x65\n" |
" movl (%k1),%k0" |
: "=r" (result) |
: "r" (offset)); |
return result; |
} |
|
#endif /* !_POSIX_SOURCE */ |
#endif /* !__STRICT_ANSI__ */ |
#endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ |
|
#ifndef __dj_ENFORCE_FUNCTION_CALLS |
#endif /* !__dj_ENFORCE_FUNCTION_CALLS */ |
|
#ifdef __cplusplus |
} |
#endif |
|
#endif /* !__dj_include_sys_farptr_h_ */ |