Back to index

glibc  2.9
i386.h
Go to the documentation of this file.
00001 /* Copyright (C) 1994, 1997 Free Software Foundation, Inc.
00002    Contributed by Joel Sherrill (jsherril@redstone-emh2.army.mil),
00003      On-Line Applications Research Corporation.
00004    This file is part of the GNU C Library.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 /*  i386.h
00022  *
00023  *  This file contains macros which are used to access i80386
00024  *  registers which are not addressable by C.  This file contains
00025  *  functions which are useful to those developing target
00026  *  specific support routines.
00027  */
00028 
00029 #ifndef i386_h__
00030 #define i386_h__
00031 
00032 typedef unsigned char   unsigned8;
00033 typedef unsigned short  unsigned16;
00034 typedef unsigned int    unsigned32;
00035 
00036 #define disable_intr( isrlevel ) \
00037   { (isrlevel) = 0; \
00038     asm volatile ( "pushf ; \
00039                   pop  %0 ; \
00040                   cli   " \
00041                   : "=r" ((isrlevel)) : "0" ((isrlevel)) ); \
00042   }
00043 
00044 
00045 #define enable_intr( isrlevel ) \
00046   { asm volatile ( "push %0 ; \
00047                   popf " \
00048                   : "=r" ((isrlevel)) : "0" ((isrlevel)) ); \
00049   }
00050 
00051 #define delay( _microseconds ) \
00052   { \
00053     unsigned32 _counter; \
00054     \
00055     _counter = (_microseconds); \
00056     \
00057     asm volatile ( "0: nop;" \
00058                  " mov %0,%0 ;" \
00059                  " loop 0" : "=c" (_counter) \
00060                                   : "0"  (_counter) \
00061                ); \
00062     \
00063   }
00064 
00065 /* segment access functions */
00066 
00067 static inline unsigned16 get_cs()
00068 {
00069   register unsigned16 segment = 0;
00070 
00071   asm volatile ( "movw %%cs,%0" : "=r" (segment) : "0" (segment) );
00072 
00073   return segment;
00074 }
00075 
00076 static inline unsigned16 get_ds()
00077 {
00078   register unsigned16 segment = 0;
00079 
00080   asm volatile ( "movw %%ds,%0" : "=r" (segment) : "0" (segment) );
00081 
00082   return segment;
00083 }
00084 
00085 static inline unsigned16 get_es()
00086 {
00087   register unsigned16 segment = 0;
00088 
00089   asm volatile ( "movw %%es,%0" : "=r" (segment) : "0" (segment) );
00090 
00091   return segment;
00092 }
00093 
00094 static inline unsigned16 get_ss()
00095 {
00096   register unsigned16 segment = 0;
00097 
00098   asm volatile ( "movw %%ss,%0" : "=r" (segment) : "0" (segment) );
00099 
00100   return segment;
00101 }
00102 
00103 static inline unsigned16 get_fs()
00104 {
00105   register unsigned16 segment = 0;
00106 
00107   asm volatile ( "movw %%fs,%0" : "=r" (segment) : "0" (segment) );
00108 
00109   return segment;
00110 }
00111 
00112 static inline unsigned16 get_gs()
00113 {
00114   register unsigned16 segment = 0;
00115 
00116   asm volatile ( "movw %%gs,%0" : "=r" (segment) : "0" (segment) );
00117 
00118   return segment;
00119 }
00120 
00121 /* i80x86 I/O instructions */
00122 
00123 #define outport_byte( _port, _value ) \
00124    { register unsigned16 __port  = _port; \
00125      register unsigned8  __value = _value; \
00126      \
00127      asm volatile ( "outb %0,%1" : "=a" (__value), "=d" (__port) \
00128                              : "0"   (__value), "1"  (__port) \
00129                 ); \
00130    }
00131 
00132 #define outport_word( _port, _value ) \
00133    { register unsigned16 __port  = _port; \
00134      register unsigned16 __value = _value; \
00135      \
00136      asm volatile ( "outw %0,%1" : "=a" (__value), "=d" (__port) \
00137                              : "0"   (__value), "1"  (__port) \
00138                 ); \
00139    }
00140 
00141 #define outport_long( _port, _value ) \
00142    { register unsigned16 __port  = _port; \
00143      register unsigned32 __value = _value; \
00144      \
00145      asm volatile ( "outl %0,%1" : "=a" (__value), "=d" (__port) \
00146                              : "0"   (__value), "1"  (__port) \
00147                 ); \
00148    }
00149 
00150 #define inport_byte( _port, _value ) \
00151    { register unsigned16 __port  = _port; \
00152      register unsigned8  __value = 0; \
00153      \
00154      asm volatile ( "inb %1,%0" : "=a" (__value), "=d" (__port) \
00155                             : "0"   (__value), "1"  (__port) \
00156                 ); \
00157      _value = __value; \
00158    }
00159 
00160 #define inport_word( _port, _value ) \
00161    { register unsigned16 __port  = _port; \
00162      register unsigned16 __value = 0; \
00163      \
00164      asm volatile ( "inw %1,%0" : "=a" (__value), "=d" (__port) \
00165                             : "0"   (__value), "1"  (__port) \
00166                 ); \
00167      _value = __value; \
00168    }
00169 
00170 #define inport_long( _port, _value ) \
00171    { register unsigned16 __port  = _port; \
00172      register unsigned32 __value = 0; \
00173      \
00174      asm volatile ( "inl %1,%0" : "=a" (__value), "=d" (__port) \
00175                             : "0"   (__value), "1"  (__port) \
00176                 ); \
00177      _value = __value; \
00178    }
00179 
00180 /* structures */
00181 
00182 /* See Chapter 5 - Memory Management in i386 manual */
00183 
00184 struct GDT_slot {
00185   unsigned16 limit_0_15;
00186   unsigned16 base_0_15;
00187   unsigned8  base_16_23;
00188   unsigned8  type_dt_dpl_p;
00189   unsigned8  limit_16_19_granularity;
00190   unsigned8  base_24_31;
00191 };
00192 
00193 /* See Chapter 9 - Exceptions and Interrupts in i386 manual
00194  *
00195  *  NOTE: This is the IDT entry for interrupt gates ONLY.
00196  */
00197 
00198 struct IDT_slot {
00199   unsigned16 offset_0_15;
00200   unsigned16 segment_selector;
00201   unsigned8  reserved;
00202   unsigned8  p_dpl;
00203   unsigned16 offset_16_31;
00204 };
00205 
00206 struct DTR_load_save_format {
00207   unsigned16 limit;
00208   unsigned32 physical_address;
00209 };
00210 
00211 /* variables */
00212 
00213 extern struct IDT_slot Interrupt_descriptor_table[ 256 ];
00214 extern struct GDT_slot Global_descriptor_table[ 8192 ];
00215 
00216 /* functions */
00217 
00218 #ifdef CPU_INITIALIZE
00219 #define EXTERN
00220 #else
00221 #undef EXTERN
00222 #define EXTERN extern
00223 #endif
00224 
00225 void *Logical_to_physical(
00226   unsigned16  segment,
00227   void             *address
00228 );
00229 
00230 void *Physical_to_logical(
00231   unsigned16  segment,
00232   void             *address
00233 );
00234 
00235 /* complicated static inline functions */
00236 
00237 #define get_GDTR( _gdtr_address ) \
00238   { \
00239     void                        *_gdtr = (_gdtr_address); \
00240     \
00241     asm volatile( "sgdt   (%0)" : "=r" (_gdtr) : "0" (_gdtr) ); \
00242   }
00243 
00244 #define get_GDT_slot( _gdtr_base, _segment, _slot_address ) \
00245   { \
00246     register unsigned32  _gdt_slot  = (_gdtr_base) + (_segment); \
00247     register volatile void    *_slot      = (_slot_address); \
00248     register unsigned32  _temporary = 0; \
00249     \
00250     asm volatile( "movl %%gs:(%0),%1 ; \
00251                  movl %1,(%2) ; \
00252                  movl %%gs:4(%0),%1 ; \
00253                  movl %1,4(%2)"  \
00254                    : "=r" (_gdt_slot), "=r" (_temporary), "=r" (_slot) \
00255                    : "0"  (_gdt_slot), "1"  (_temporary), "2"  (_slot) \
00256               );  \
00257   }
00258 
00259 #define set_GDT_slot( _gdtr_base, _segment, _slot_address ) \
00260   { \
00261     register unsigned32  _gdt_slot  = (_gdtr_base) + (_segment); \
00262     register volatile void    *_slot      = (_slot_address); \
00263     register unsigned32  _temporary = 0; \
00264     \
00265     asm volatile( "movl (%2),%1 ; \
00266                  movl %1,%%gs:(%0) ; \
00267                  movl 4(%2),%1 ; \
00268                  movl %1,%%gs:4(%0) \
00269                 " \
00270                    : "=r" (_gdt_slot), "=r" (_temporary), "=r" (_slot) \
00271                    : "0"  (_gdt_slot), "1"  (_temporary), "2"  (_slot) \
00272               );  \
00273   }
00274 
00275 static inline void set_segment(
00276   unsigned16 segment,
00277   unsigned32 base,
00278   unsigned32 limit
00279 )
00280 {
00281   struct DTR_load_save_format  gdtr;
00282   volatile struct GDT_slot     Gdt_slot;
00283   volatile struct GDT_slot    *gdt_slot = &Gdt_slot;
00284   unsigned16             tmp_segment = 0;
00285   unsigned32             limit_adjusted;
00286 
00287 
00288   /* load physical address of the GDT */
00289 
00290   get_GDTR( &gdtr );
00291 
00292   gdt_slot->type_dt_dpl_p  = 0x92;             /* present, dpl=0,      */
00293                                           /* application=1,       */
00294                                           /* type=data read/write */
00295   gdt_slot->limit_16_19_granularity = 0x40;    /* 32 bit segment       */
00296 
00297   limit_adjusted = limit;
00298   if ( limit > 4095 ) {
00299     gdt_slot->limit_16_19_granularity |= 0x80; /* set granularity bit */
00300     limit_adjusted /= 4096;
00301   }
00302 
00303   gdt_slot->limit_16_19_granularity |= (limit_adjusted >> 16) & 0xff;
00304   gdt_slot->limit_0_15               = limit_adjusted & 0xffff;
00305 
00306   gdt_slot->base_0_15  = base & 0xffff;
00307   gdt_slot->base_16_23 = (base >> 16) & 0xff;
00308   gdt_slot->base_24_31 = (base >> 24);
00309 
00310   set_GDT_slot( gdtr.physical_address, segment, gdt_slot );
00311 
00312   /* Now, reload all segment registers so the limit takes effect. */
00313 
00314   asm volatile( "movw %%ds,%0 ; movw %0,%%ds\n"
00315               "movw %%es,%0 ; movw %0,%%es\n"
00316               "movw %%fs,%0 ; movw %0,%%fs\n"
00317               "movw %%gs,%0 ; movw %0,%%gs\n"
00318               "movw %%ss,%0 ; movw %0,%%ss"
00319                  : "=r" (tmp_segment)
00320                  : "0"  (tmp_segment)
00321              );
00322 
00323 }
00324 
00325 #endif
00326 /* end of include file */