source: rtems/c/src/exec/score/cpu/i386/i386.h @ 93bea77

4.104.114.84.95
Last change on this file since 93bea77 was 5e9b32b, checked in by Joel Sherrill <joel.sherrill@…>, on 09/26/95 at 19:27:15

posix support initially added

  • Property mode set to 100644
File size: 12.3 KB
Line 
1/*  i386.h
2 *
3 *  This include file contains information pertaining to the Intel
4 *  i386 processor.
5 *
6 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
7 *  On-Line Applications Research Corporation (OAR).
8 *  All rights assigned to U.S. Government, 1994.
9 *
10 *  This material may be reproduced by or for the U.S. Government pursuant
11 *  to the copyright license under the clause at DFARS 252.227-7013.  This
12 *  notice must appear in all copies of this file and its derivatives.
13 *
14 *  $Id$
15 */
16
17#ifndef __i386_h
18#define __i386_h
19
20#ifdef __cplusplus
21extern "C" {
22#endif
23
24/*
25 *  The following define the CPU Family and Model within the family
26 *
27 *  NOTE: The string "REPLACE_THIS_WITH_THE_CPU_MODEL" is replaced
28 *        with the name of the appropriate macro for this target CPU.
29 */
30
31#ifdef i386
32#undef i386
33#endif
34#define i386 1
35
36#ifdef REPLACE_THIS_WITH_THE_CPU_MODEL
37#undef REPLACE_THIS_WITH_THE_CPU_MODEL
38#endif
39#define REPLACE_THIS_WITH_THE_CPU_MODEL
40
41#ifdef REPLACE_THIS_WITH_THE_BSP
42#undef REPLACE_THIS_WITH_THE_BSP
43#endif
44#define REPLACE_THIS_WITH_THE_BSP
45
46/*
47 *  This section contains the information required to build
48 *  RTEMS for a particular member of the Intel i386
49 *  family when executing in protected mode.  It does
50 *  this by setting variables to indicate which implementation
51 *  dependent features are present in a particular member
52 *  of the family.
53 *
54 *  Currently recognized:
55 *    i386_fp    (i386 DX or SX w/i387)
56 *    i386_fp    (i386 DX or SX w/o i387)
57 *    i486dx
58 *    i486sx
59 *    pentium
60 *
61 *  Floating point is the only feature which currently varies.  Eventually
62 *  the i486-plus level instruction for endian swapping should be added
63 *  to this feature list.
64 */
65
66#if defined(i386_fp)
67
68#define CPU_MODEL_NAME  "i386 with i387"
69#define I386_HAS_FPU 1
70
71#elif defined(i386_nofp)
72
73#define CPU_MODEL_NAME  "i386 w/o i387"
74#define I386_HAS_FPU 1
75
76#elif defined(i486dx)
77
78#define CPU_MODEL_NAME  "i486dx"
79#define I386_HAS_FPU 1
80
81#elif defined(i486sx)
82
83#define CPU_MODEL_NAME  "i486sx"
84#define I386_HAS_FPU 0
85
86#elif defined(pentium)
87
88#define CPU_MODEL_NAME  "Pentium"
89#define I386_HAS_FPU 1
90
91#else
92
93#error "Unsupported CPU Model"
94
95#endif
96
97/*
98 *  Define the name of the CPU family.
99 */
100
101#define CPU_NAME "Intel i386"
102
103#ifndef ASM
104
105/*
106 *  Structure which makes it easier to deal with LxDT and SxDT instructions.
107 */
108 
109typedef struct {
110  unsigned short limit;
111  unsigned short physical_address[ 2 ];
112} i386_DTR_load_save_format;
113 
114/* See Chapter 5 - Memory Management in i386 manual */
115 
116typedef struct {
117  unsigned short limit_0_15;
118  unsigned short base_0_15;
119  unsigned char  base_16_23;
120  unsigned char  type_dt_dpl_p;
121  unsigned char  limit_16_19_granularity;
122  unsigned char  base_24_31;
123}   i386_GDT_slot;
124 
125/* See Chapter 9 - Exceptions and Interrupts in i386 manual
126 *
127 *  NOTE: This is the IDT entry for interrupt gates ONLY.
128 */
129 
130typedef struct {
131  unsigned short offset_0_15;
132  unsigned short segment_selector;
133  unsigned char  reserved;
134  unsigned char  p_dpl;
135  unsigned short offset_16_31;
136}   i386_IDT_slot;
137
138/*
139 *  Interrupt Level Macros
140 */
141
142#define i386_disable_interrupts( _level ) \
143  { \
144    _level = 0;   /* avoids warnings */ \
145    asm volatile ( "pushf ; \
146                    cli ; \
147                    pop %0" \
148                    : "=r" ((_level)) : "0" ((_level)) \
149    ); \
150  }
151
152#define i386_enable_interrupts( _level )  \
153  { \
154    asm volatile ( "push %0 ; \
155                    popf" \
156                    : "=r" ((_level)) : "0" ((_level)) \
157    ); \
158  }
159
160#define i386_flash_interrupts( _level ) \
161  { \
162    asm volatile ( "push %0 ; \
163                    popf ; \
164                    cli" \
165                    : "=r" ((_level)) : "0" ((_level)) \
166    ); \
167  }
168
169#define i386_get_interrupt_level( _level ) \
170  do { \
171    register unsigned32 _eflags = 0; \
172    \
173    asm volatile ( "pushf ; \
174                    pop %0" \
175                    : "=r" ((_eflags)) : "0" ((_eflags)) \
176    ); \
177    \
178    _level = (_eflags & 0x0200) ? 0 : 1; \
179  } while (0)
180
181/*
182 *  The following routine swaps the endian format of an unsigned int.
183 *  It must be static so it can be referenced indirectly.
184 */
185
186static inline unsigned int i386_swap_U32(
187  unsigned int value
188)
189{
190  asm volatile( "rorw  $8,%%ax;"
191                "rorl  $16,%0;"
192                "rorw  $8,%%ax" : "=a" (value) : "0" (value) );
193  return( value );
194}
195
196/*
197 *  Segment Access Routines
198 *
199 *  NOTE:  Unfortunately, these are still static inlines even when the
200 *         "macro" implementation of the generic code is used.
201 */
202
203static inline unsigned short i386_get_cs()
204{
205  register unsigned short segment = 0;
206
207  asm volatile ( "movw %%cs,%0" : "=r" (segment) : "0" (segment) );
208
209  return segment;
210}
211
212static inline unsigned short i386_get_ds()
213{
214  register unsigned short segment = 0;
215
216  asm volatile ( "movw %%ds,%0" : "=r" (segment) : "0" (segment) );
217
218  return segment;
219}
220
221static inline unsigned short i386_get_es()
222{
223  register unsigned short segment = 0;
224
225  asm volatile ( "movw %%es,%0" : "=r" (segment) : "0" (segment) );
226
227  return segment;
228}
229
230static inline unsigned short i386_get_ss()
231{
232  register unsigned short segment = 0;
233
234  asm volatile ( "movw %%ss,%0" : "=r" (segment) : "0" (segment) );
235
236  return segment;
237}
238
239static inline unsigned short i386_get_fs()
240{
241  register unsigned short segment = 0;
242
243  asm volatile ( "movw %%fs,%0" : "=r" (segment) : "0" (segment) );
244
245  return segment;
246}
247
248static inline unsigned short i386_get_gs()
249{
250  register unsigned short segment = 0;
251
252  asm volatile ( "movw %%gs,%0" : "=r" (segment) : "0" (segment) );
253
254  return segment;
255}
256
257/*
258 *  IO Port Access Routines
259 */
260
261#define i386_outport_byte( _port, _value ) \
262   { register unsigned short __port  = _port; \
263     register unsigned char  __value = _value; \
264     \
265     asm volatile ( "outb %0,%1" : "=a" (__value), "=d" (__port) \
266                                 : "0"   (__value), "1"  (__port) \
267                  ); \
268   }
269
270#define i386_outport_word( _port, _value ) \
271   { register unsigned short __port  = _port; \
272     register unsigned short __value = _value; \
273     \
274     asm volatile ( "outw %0,%1" : "=a" (__value), "=d" (__port) \
275                                 : "0"   (__value), "1"  (__port) \
276                  ); \
277   }
278
279#define i386_outport_long( _port, _value ) \
280   { register unsigned short __port  = _port; \
281     register unsigned int  __value = _value; \
282     \
283     asm volatile ( "outl %0,%1" : "=a" (__value), "=d" (__port) \
284                                 : "0"   (__value), "1"  (__port) \
285                  ); \
286   }
287
288#define i386_inport_byte( _port, _value ) \
289   { register unsigned short __port  = _port; \
290     register unsigned char  __value = 0; \
291     \
292     asm volatile ( "inb %1,%0" : "=a" (__value), "=d" (__port) \
293                                : "0"   (__value), "1"  (__port) \
294                  ); \
295     _value = __value; \
296   }
297
298#define i386_inport_word( _port, _value ) \
299   { register unsigned short __port  = _port; \
300     register unsigned short __value = 0; \
301     \
302     asm volatile ( "inw %1,%0" : "=a" (__value), "=d" (__port) \
303                                : "0"   (__value), "1"  (__port) \
304                  ); \
305     _value = __value; \
306   }
307
308#define i386_inport_long( _port, _value ) \
309   { register unsigned short __port  = _port; \
310     register unsigned int  __value = 0; \
311     \
312     asm volatile ( "inl %1,%0" : "=a" (__value), "=d" (__port) \
313                                : "0"   (__value), "1"  (__port) \
314                  ); \
315     _value = __value; \
316   }
317
318/*
319 *  Descriptor Table helper routines
320 */
321
322
323#define i386_get_GDTR( _gdtr_address ) \
324  { \
325    void *_gdtr = (_gdtr_address); \
326    \
327    asm volatile( "sgdt   (%0)" : "=r" (_gdtr) : "0" (_gdtr) ); \
328  }
329
330#define i386_get_GDT_slot( _gdtr_base, _segment, _slot_address ) \
331  { \
332    register unsigned int   _gdt_slot  = (_gdtr_base) + (_segment); \
333    register volatile void *_slot      = (_slot_address); \
334    register unsigned int   _temporary = 0; \
335    \
336    asm volatile( "movl %%gs:(%0),%1 ; \
337                   movl %1,(%2) ; \
338                   movl %%gs:4(%0),%1 ; \
339                   movl %1,4(%2)"  \
340                     : "=r" (_gdt_slot), "=r" (_temporary), "=r" (_slot) \
341                     : "0"  (_gdt_slot), "1"  (_temporary), "2"  (_slot) \
342                );  \
343  }
344
345#define i386_set_GDT_slot( _gdtr_base, _segment, _slot_address ) \
346  { \
347    register unsigned int   _gdt_slot  = (_gdtr_base) + (_segment); \
348    register volatile void *_slot      = (_slot_address); \
349    register unsigned int   _temporary = 0; \
350    \
351    asm volatile( "movl (%2),%1 ; \
352                   movl %1,%%gs:(%0) ; \
353                   movl 4(%2),%1 ; \
354                   movl %1,%%gs:4(%0) \
355                  " \
356                     : "=r" (_gdt_slot), "=r" (_temporary), "=r" (_slot) \
357                     : "0"  (_gdt_slot), "1"  (_temporary), "2"  (_slot) \
358                );  \
359  }
360
361static inline void i386_set_segment(
362  unsigned short segment,
363  unsigned int  base,
364  unsigned int  limit
365)
366{
367  i386_DTR_load_save_format         gdtr;
368  volatile i386_GDT_slot            Gdt_slot;
369  volatile i386_GDT_slot           *gdt_slot = &Gdt_slot;
370  unsigned short                    tmp_segment = 0;
371  unsigned int                      limit_adjusted;
372
373  /* load physical address of the GDT */
374
375  i386_get_GDTR( &gdtr );
376
377  gdt_slot->type_dt_dpl_p  = 0x92;             /* present, dpl=0,      */
378                                               /* application=1,       */
379                                               /* type=data read/write */
380  gdt_slot->limit_16_19_granularity = 0x40;    /* 32 bit segment       */
381
382  limit_adjusted = limit;
383  if ( limit > 4095 ) {
384    gdt_slot->limit_16_19_granularity |= 0x80; /* set granularity bit */
385    limit_adjusted /= 4096;
386  }
387
388  gdt_slot->limit_16_19_granularity |= (limit_adjusted >> 16) & 0xff;
389  gdt_slot->limit_0_15               = limit_adjusted & 0xffff;
390
391  gdt_slot->base_0_15  = base & 0xffff;
392  gdt_slot->base_16_23 = (base >> 16) & 0xff;
393  gdt_slot->base_24_31 = (base >> 24);
394
395  i386_set_GDT_slot(
396    gdtr.physical_address[0] + (gdtr.physical_address[1] << 16),
397    segment,
398    gdt_slot
399  );
400
401  /* Now, reload all segment registers so the limit takes effect. */
402
403  asm volatile( "movw %%ds,%0 ; movw %0,%%ds
404                 movw %%es,%0 ; movw %0,%%es
405                 movw %%fs,%0 ; movw %0,%%fs
406                 movw %%gs,%0 ; movw %0,%%gs
407                 movw %%ss,%0 ; movw %0,%%ss"
408                   : "=r" (tmp_segment)
409                   : "0"  (tmp_segment)
410              );
411
412}
413
414/* routines */
415
416/*
417 *  i386_Logical_to_physical
418 *
419 *  Converts logical address to physical address.
420 */
421
422void *i386_Logical_to_physical(
423  unsigned short  segment,
424  void           *address
425);
426
427/*
428 *  i386_Physical_to_logical
429 *
430 *  Converts physical address to logical address.
431 */
432
433void *i386_Physical_to_logical(
434  unsigned short  segment,
435  void           *address
436);
437
438/*
439 *  i386_Install_idt
440 *
441 *  This routine installs an IDT entry.
442 */
443
444void i386_Install_idt(
445  unsigned int   source_offset,
446  unsigned short destination_segment,
447  unsigned int   destination_offset
448);
449
450/*
451 *  "Simpler" names for a lot of the things defined in this file
452 */
453
454/* segment access routines */
455 
456#define get_cs()   i386_get_cs()
457#define get_ds()   i386_get_ds()
458#define get_es()   i386_get_es()
459#define get_ss()   i386_get_ss()
460#define get_fs()   i386_get_fs()
461#define get_gs()   i386_get_gs()
462 
463#define CPU_swap_u32( _value )  i386_swap_U32( _value )
464 
465/* i80x86 I/O instructions */
466 
467#define outport_byte( _port, _value ) i386_outport_byte( _port, _value )
468#define outport_word( _port, _value ) i386_outport_word( _port, _value )
469#define outport_long( _port, _value ) i386_outport_long( _port, _value )
470#define inport_byte( _port, _value )  i386_inport_byte( _port, _value )
471#define inport_word( _port, _value )  i386_inport_word( _port, _value )
472#define inport_long( _port, _value )  i386_inport_long( _port, _value )
473 
474/* complicated static inline functions */
475 
476#define get_GDTR( _gdtr_address ) \
477        i386_get_GDTR( _gdtr_address )
478 
479#define get_GDT_slot( _gdtr_base, _segment, _slot_address ) \
480        i386_get_GDT_slot( _gdtr_base, _segment, _slot_address )
481 
482#define set_GDT_slot( _gdtr_base, _segment, _slot_address ) \
483        i386_set_GDT_slot( _gdtr_base, _segment, _slot_address )
484 
485#define set_segment( _segment, _base, _limit ) \
486  i386_set_segment( _segment, _base, _limit )
487 
488
489#ifdef __cplusplus
490}
491#endif
492
493#endif /* !ASM */
494
495#endif
496/* end of include file */
Note: See TracBrowser for help on using the repository browser.