1 /* Copyright (C) 1994 Free Software Foundation, Inc.
2 Contributed by Joel Sherrill (jsherril@redstone-emh2.army.mil),
3 On-Line Applications Research Corporation.
5 This file is part of the GNU C Library.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with the GNU C Library; see the file COPYING.LIB. If
19 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
20 Cambridge, MA 02139, USA. */
24 * This file contains macros which are used to access i80386
25 * registers which are not addressable by C. This file contains
26 * functions which are useful to those developing target
27 * specific support routines.
33 typedef unsigned char unsigned8;
34 typedef unsigned short unsigned16;
35 typedef unsigned int unsigned32;
37 #define disable_intr( isrlevel ) \
39 asm volatile ( "pushf ; \
42 : "=r" ((isrlevel)) : "0" ((isrlevel)) ); \
46 #define enable_intr( isrlevel ) \
47 { asm volatile ( "push %0 ; \
49 : "=r" ((isrlevel)) : "0" ((isrlevel)) ); \
52 #define delay( _microseconds ) \
54 unsigned32 _counter; \
56 _counter = (_microseconds); \
58 asm volatile ( "0: nop;" \
60 " loop 0" : "=c" (_counter) \
66 /* segment access functions */
68 static inline unsigned16 get_cs()
70 register unsigned16 segment = 0;
72 asm volatile ( "movw %%cs,%0" : "=r" (segment) : "0" (segment) );
77 static inline unsigned16 get_ds()
79 register unsigned16 segment = 0;
81 asm volatile ( "movw %%ds,%0" : "=r" (segment) : "0" (segment) );
86 static inline unsigned16 get_es()
88 register unsigned16 segment = 0;
90 asm volatile ( "movw %%es,%0" : "=r" (segment) : "0" (segment) );
95 static inline unsigned16 get_ss()
97 register unsigned16 segment = 0;
99 asm volatile ( "movw %%ss,%0" : "=r" (segment) : "0" (segment) );
104 static inline unsigned16 get_fs()
106 register unsigned16 segment = 0;
108 asm volatile ( "movw %%fs,%0" : "=r" (segment) : "0" (segment) );
113 static inline unsigned16 get_gs()
115 register unsigned16 segment = 0;
117 asm volatile ( "movw %%gs,%0" : "=r" (segment) : "0" (segment) );
122 /* i80x86 I/O instructions */
124 #define outport_byte( _port, _value ) \
125 { register unsigned16 __port = _port; \
126 register unsigned8 __value = _value; \
128 asm volatile ( "outb %0,%1" : "=a" (__value), "=d" (__port) \
129 : "0" (__value), "1" (__port) \
133 #define outport_word( _port, _value ) \
134 { register unsigned16 __port = _port; \
135 register unsigned16 __value = _value; \
137 asm volatile ( "outw %0,%1" : "=a" (__value), "=d" (__port) \
138 : "0" (__value), "1" (__port) \
142 #define outport_long( _port, _value ) \
143 { register unsigned16 __port = _port; \
144 register unsigned32 __value = _value; \
146 asm volatile ( "outl %0,%1" : "=a" (__value), "=d" (__port) \
147 : "0" (__value), "1" (__port) \
151 #define inport_byte( _port, _value ) \
152 { register unsigned16 __port = _port; \
153 register unsigned8 __value = 0; \
155 asm volatile ( "inb %1,%0" : "=a" (__value), "=d" (__port) \
156 : "0" (__value), "1" (__port) \
161 #define inport_word( _port, _value ) \
162 { register unsigned16 __port = _port; \
163 register unsigned16 __value = 0; \
165 asm volatile ( "inw %1,%0" : "=a" (__value), "=d" (__port) \
166 : "0" (__value), "1" (__port) \
171 #define inport_long( _port, _value ) \
172 { register unsigned16 __port = _port; \
173 register unsigned32 __value = 0; \
175 asm volatile ( "inl %1,%0" : "=a" (__value), "=d" (__port) \
176 : "0" (__value), "1" (__port) \
183 /* See Chapter 5 - Memory Management in i386 manual */
186 unsigned16 limit_0_15;
187 unsigned16 base_0_15;
188 unsigned8 base_16_23;
189 unsigned8 type_dt_dpl_p;
190 unsigned8 limit_16_19_granularity;
191 unsigned8 base_24_31;
194 /* See Chapter 9 - Exceptions and Interrupts in i386 manual
196 * NOTE: This is the IDT entry for interrupt gates ONLY.
200 unsigned16 offset_0_15;
201 unsigned16 segment_selector;
204 unsigned16 offset_16_31;
207 struct DTR_load_save_format {
209 unsigned32 physical_address;
214 extern struct IDT_slot Interrupt_descriptor_table[ 256 ];
215 extern struct GDT_slot Global_descriptor_table[ 8192 ];
219 #ifdef CPU_INITIALIZE
223 #define EXTERN extern
226 void *Logical_to_physical(
231 void *Physical_to_logical(
236 /* complicated static inline functions */
238 #define get_GDTR( _gdtr_address ) \
240 void *_gdtr = (_gdtr_address); \
242 asm volatile( "sgdt (%0)" : "=r" (_gdtr) : "0" (_gdtr) ); \
245 #define get_GDT_slot( _gdtr_base, _segment, _slot_address ) \
247 register unsigned32 _gdt_slot = (_gdtr_base) + (_segment); \
248 register volatile void *_slot = (_slot_address); \
249 register unsigned32 _temporary = 0; \
251 asm volatile( "movl %%gs:(%0),%1 ; \
253 movl %%gs:4(%0),%1 ; \
255 : "=r" (_gdt_slot), "=r" (_temporary), "=r" (_slot) \
256 : "0" (_gdt_slot), "1" (_temporary), "2" (_slot) \
260 #define set_GDT_slot( _gdtr_base, _segment, _slot_address ) \
262 register unsigned32 _gdt_slot = (_gdtr_base) + (_segment); \
263 register volatile void *_slot = (_slot_address); \
264 register unsigned32 _temporary = 0; \
266 asm volatile( "movl (%2),%1 ; \
267 movl %1,%%gs:(%0) ; \
271 : "=r" (_gdt_slot), "=r" (_temporary), "=r" (_slot) \
272 : "0" (_gdt_slot), "1" (_temporary), "2" (_slot) \
276 static inline void set_segment(
282 struct DTR_load_save_format gdtr;
283 volatile struct GDT_slot Gdt_slot;
284 volatile struct GDT_slot *gdt_slot = &Gdt_slot;
285 unsigned16 tmp_segment = 0;
286 unsigned32 limit_adjusted;
289 /* load physical address of the GDT */
293 gdt_slot->type_dt_dpl_p = 0x92; /* present, dpl=0, */
295 /* type=data read/write */
296 gdt_slot->limit_16_19_granularity = 0x40; /* 32 bit segment */
298 limit_adjusted = limit;
299 if ( limit > 4095 ) {
300 gdt_slot->limit_16_19_granularity |= 0x80; /* set granularity bit */
301 limit_adjusted /= 4096;
304 gdt_slot->limit_16_19_granularity |= (limit_adjusted >> 16) & 0xff;
305 gdt_slot->limit_0_15 = limit_adjusted & 0xffff;
307 gdt_slot->base_0_15 = base & 0xffff;
308 gdt_slot->base_16_23 = (base >> 16) & 0xff;
309 gdt_slot->base_24_31 = (base >> 24);
311 set_GDT_slot( gdtr.physical_address, segment, gdt_slot );
313 /* Now, reload all segment registers so the limit takes effect. */
315 asm volatile( "movw %%ds,%0 ; movw %0,%%ds
316 movw %%es,%0 ; movw %0,%%es
317 movw %%fs,%0 ; movw %0,%%fs
318 movw %%gs,%0 ; movw %0,%%gs
319 movw %%ss,%0 ; movw %0,%%ss"
327 /* end of include file */