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

4.104.114.84.95
Last change on this file since a05de51 was dd6dddc, checked in by Joel Sherrill <joel.sherrill@…>, on 07/01/98 at 21:33:11

Fixed typo.

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