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

4.104.114.84.95
Last change on this file since 541dfb2 was 541dfb2, checked in by Joel Sherrill <joel.sherrill@…>, on Jan 29, 1997 at 12:22:24 AM

Removed definitions which are now in targopts.h. This eliminates the
need for the "sed'ing" of this file. This should be a significant win
when addressing non-unix host and non-gnu toolsets.

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