2004-10-04 Roland McGrath <roland@redhat.com>
[glibc-ports.git] / sysdeps / standalone / i386 / i386.h
blob364e8abb3da715970549825faf5aa784b2162484
1 /* Copyright (C) 1994, 1997 Free Software Foundation, Inc.
2 Contributed by Joel Sherrill (jsherril@redstone-emh2.army.mil),
3 On-Line Applications Research Corporation.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
21 /* i386.h
23 * This file contains macros which are used to access i80386
24 * registers which are not addressable by C. This file contains
25 * functions which are useful to those developing target
26 * specific support routines.
29 #ifndef i386_h__
30 #define i386_h__
32 typedef unsigned char unsigned8;
33 typedef unsigned short unsigned16;
34 typedef unsigned int unsigned32;
36 #define disable_intr( isrlevel ) \
37 { (isrlevel) = 0; \
38 asm volatile ( "pushf ; \
39 pop %0 ; \
40 cli " \
41 : "=r" ((isrlevel)) : "0" ((isrlevel)) ); \
45 #define enable_intr( isrlevel ) \
46 { asm volatile ( "push %0 ; \
47 popf " \
48 : "=r" ((isrlevel)) : "0" ((isrlevel)) ); \
51 #define delay( _microseconds ) \
52 { \
53 unsigned32 _counter; \
55 _counter = (_microseconds); \
57 asm volatile ( "0: nop;" \
58 " mov %0,%0 ;" \
59 " loop 0" : "=c" (_counter) \
60 : "0" (_counter) \
61 ); \
65 /* segment access functions */
67 static inline unsigned16 get_cs()
69 register unsigned16 segment = 0;
71 asm volatile ( "movw %%cs,%0" : "=r" (segment) : "0" (segment) );
73 return segment;
76 static inline unsigned16 get_ds()
78 register unsigned16 segment = 0;
80 asm volatile ( "movw %%ds,%0" : "=r" (segment) : "0" (segment) );
82 return segment;
85 static inline unsigned16 get_es()
87 register unsigned16 segment = 0;
89 asm volatile ( "movw %%es,%0" : "=r" (segment) : "0" (segment) );
91 return segment;
94 static inline unsigned16 get_ss()
96 register unsigned16 segment = 0;
98 asm volatile ( "movw %%ss,%0" : "=r" (segment) : "0" (segment) );
100 return segment;
103 static inline unsigned16 get_fs()
105 register unsigned16 segment = 0;
107 asm volatile ( "movw %%fs,%0" : "=r" (segment) : "0" (segment) );
109 return segment;
112 static inline unsigned16 get_gs()
114 register unsigned16 segment = 0;
116 asm volatile ( "movw %%gs,%0" : "=r" (segment) : "0" (segment) );
118 return segment;
121 /* i80x86 I/O instructions */
123 #define outport_byte( _port, _value ) \
124 { register unsigned16 __port = _port; \
125 register unsigned8 __value = _value; \
127 asm volatile ( "outb %0,%1" : "=a" (__value), "=d" (__port) \
128 : "0" (__value), "1" (__port) \
129 ); \
132 #define outport_word( _port, _value ) \
133 { register unsigned16 __port = _port; \
134 register unsigned16 __value = _value; \
136 asm volatile ( "outw %0,%1" : "=a" (__value), "=d" (__port) \
137 : "0" (__value), "1" (__port) \
138 ); \
141 #define outport_long( _port, _value ) \
142 { register unsigned16 __port = _port; \
143 register unsigned32 __value = _value; \
145 asm volatile ( "outl %0,%1" : "=a" (__value), "=d" (__port) \
146 : "0" (__value), "1" (__port) \
147 ); \
150 #define inport_byte( _port, _value ) \
151 { register unsigned16 __port = _port; \
152 register unsigned8 __value = 0; \
154 asm volatile ( "inb %1,%0" : "=a" (__value), "=d" (__port) \
155 : "0" (__value), "1" (__port) \
156 ); \
157 _value = __value; \
160 #define inport_word( _port, _value ) \
161 { register unsigned16 __port = _port; \
162 register unsigned16 __value = 0; \
164 asm volatile ( "inw %1,%0" : "=a" (__value), "=d" (__port) \
165 : "0" (__value), "1" (__port) \
166 ); \
167 _value = __value; \
170 #define inport_long( _port, _value ) \
171 { register unsigned16 __port = _port; \
172 register unsigned32 __value = 0; \
174 asm volatile ( "inl %1,%0" : "=a" (__value), "=d" (__port) \
175 : "0" (__value), "1" (__port) \
176 ); \
177 _value = __value; \
180 /* structures */
182 /* See Chapter 5 - Memory Management in i386 manual */
184 struct GDT_slot {
185 unsigned16 limit_0_15;
186 unsigned16 base_0_15;
187 unsigned8 base_16_23;
188 unsigned8 type_dt_dpl_p;
189 unsigned8 limit_16_19_granularity;
190 unsigned8 base_24_31;
193 /* See Chapter 9 - Exceptions and Interrupts in i386 manual
195 * NOTE: This is the IDT entry for interrupt gates ONLY.
198 struct IDT_slot {
199 unsigned16 offset_0_15;
200 unsigned16 segment_selector;
201 unsigned8 reserved;
202 unsigned8 p_dpl;
203 unsigned16 offset_16_31;
206 struct DTR_load_save_format {
207 unsigned16 limit;
208 unsigned32 physical_address;
211 /* variables */
213 extern struct IDT_slot Interrupt_descriptor_table[ 256 ];
214 extern struct GDT_slot Global_descriptor_table[ 8192 ];
216 /* functions */
218 #ifdef CPU_INITIALIZE
219 #define EXTERN
220 #else
221 #undef EXTERN
222 #define EXTERN extern
223 #endif
225 void *Logical_to_physical(
226 unsigned16 segment,
227 void *address
230 void *Physical_to_logical(
231 unsigned16 segment,
232 void *address
235 /* complicated static inline functions */
237 #define get_GDTR( _gdtr_address ) \
239 void *_gdtr = (_gdtr_address); \
241 asm volatile( "sgdt (%0)" : "=r" (_gdtr) : "0" (_gdtr) ); \
244 #define get_GDT_slot( _gdtr_base, _segment, _slot_address ) \
246 register unsigned32 _gdt_slot = (_gdtr_base) + (_segment); \
247 register volatile void *_slot = (_slot_address); \
248 register unsigned32 _temporary = 0; \
250 asm volatile( "movl %%gs:(%0),%1 ; \
251 movl %1,(%2) ; \
252 movl %%gs:4(%0),%1 ; \
253 movl %1,4(%2)" \
254 : "=r" (_gdt_slot), "=r" (_temporary), "=r" (_slot) \
255 : "0" (_gdt_slot), "1" (_temporary), "2" (_slot) \
256 ); \
259 #define set_GDT_slot( _gdtr_base, _segment, _slot_address ) \
261 register unsigned32 _gdt_slot = (_gdtr_base) + (_segment); \
262 register volatile void *_slot = (_slot_address); \
263 register unsigned32 _temporary = 0; \
265 asm volatile( "movl (%2),%1 ; \
266 movl %1,%%gs:(%0) ; \
267 movl 4(%2),%1 ; \
268 movl %1,%%gs:4(%0) \
270 : "=r" (_gdt_slot), "=r" (_temporary), "=r" (_slot) \
271 : "0" (_gdt_slot), "1" (_temporary), "2" (_slot) \
272 ); \
275 static inline void set_segment(
276 unsigned16 segment,
277 unsigned32 base,
278 unsigned32 limit
281 struct DTR_load_save_format gdtr;
282 volatile struct GDT_slot Gdt_slot;
283 volatile struct GDT_slot *gdt_slot = &Gdt_slot;
284 unsigned16 tmp_segment = 0;
285 unsigned32 limit_adjusted;
288 /* load physical address of the GDT */
290 get_GDTR( &gdtr );
292 gdt_slot->type_dt_dpl_p = 0x92; /* present, dpl=0, */
293 /* application=1, */
294 /* type=data read/write */
295 gdt_slot->limit_16_19_granularity = 0x40; /* 32 bit segment */
297 limit_adjusted = limit;
298 if ( limit > 4095 ) {
299 gdt_slot->limit_16_19_granularity |= 0x80; /* set granularity bit */
300 limit_adjusted /= 4096;
303 gdt_slot->limit_16_19_granularity |= (limit_adjusted >> 16) & 0xff;
304 gdt_slot->limit_0_15 = limit_adjusted & 0xffff;
306 gdt_slot->base_0_15 = base & 0xffff;
307 gdt_slot->base_16_23 = (base >> 16) & 0xff;
308 gdt_slot->base_24_31 = (base >> 24);
310 set_GDT_slot( gdtr.physical_address, segment, gdt_slot );
312 /* Now, reload all segment registers so the limit takes effect. */
314 asm volatile( "movw %%ds,%0 ; movw %0,%%ds\n"
315 "movw %%es,%0 ; movw %0,%%es\n"
316 "movw %%fs,%0 ; movw %0,%%fs\n"
317 "movw %%gs,%0 ; movw %0,%%gs\n"
318 "movw %%ss,%0 ; movw %0,%%ss"
319 : "=r" (tmp_segment)
320 : "0" (tmp_segment)
325 #endif
326 /* end of include file */