summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/i386/rtems/score/i386.h
blob: 926627dccbe51581df5ffa5450d321d4b0456f76 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/**
 * @file
 *
 * @brief Intel I386 CPU Dependent Source
 *
 * This include file contains information pertaining to the Intel
 * i386 processor.
 */

/*
 *  COPYRIGHT (c) 1989-2013.
 *  On-Line Applications Research Corporation (OAR).
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.org/license/LICENSE.
 */

#ifndef _RTEMS_SCORE_I386_H
#define _RTEMS_SCORE_I386_H

#ifdef __cplusplus
extern "C" {
#endif

/*
 *  This section contains the information required to build
 *  RTEMS for a particular member of the Intel i386
 *  family when executing in protected mode.  It does
 *  this by setting variables to indicate which implementation
 *  dependent features are present in a particular member
 *  of the family.
 *
 *  Currently recognized:
 *    i386_fp    (i386 DX or SX w/i387)
 *    i486dx
 *    pentium
 *    pentiumpro
 *
 *  CPU Model Feature Flags:
 *
 *  I386_HAS_BSWAP:  Defined to "1" if the instruction for endian swapping
 *                   (bswap) should be used.  This instruction appears to
 *                   be present in all i486's and above.
 *
 *  I386_HAS_FPU:    Defined to "1" if the CPU has an FPU.
 *                   As of at least gcc 4.7, i386 soft-float was obsoleted.
 *                   Thus this is always set to "1".
 */
#define I386_HAS_FPU 1

#if defined(__pentiumpro__)

  #define CPU_MODEL_NAME  "Pentium Pro"

#elif defined(__i586__)

  #if defined(__pentium__)
    #define CPU_MODEL_NAME "Pentium"
  #elif defined(__k6__)
    #define CPU_MODEL_NAME "K6"
  #else
    #define CPU_MODEL_NAME "i586"
  #endif

#elif defined(__i486__)

  #define CPU_MODEL_NAME  "i486dx"

#elif defined(__i386__)

  #define I386_HAS_BSWAP  0
  #define CPU_MODEL_NAME  "i386 with i387"

#else
  #error "Unknown CPU Model"
#endif

/*
 *  Set default values for CPU model feature flags
 *
 *  NOTE: These settings are chosen to reflect most of the family members.
 */
#ifndef I386_HAS_BSWAP
#define I386_HAS_BSWAP 1
#endif

/*
 *  Define the name of the CPU family.
 */
#define CPU_NAME "Intel i386"

#ifndef ASM

/*
 *  The following routine swaps the endian format of an unsigned int.
 *  It must be static so it can be referenced indirectly.
 */

static inline uint32_t i386_swap_u32(
  uint32_t value
)
{
  uint32_t lout;

#if (I386_HAS_BSWAP == 0)
  __asm__ volatile( "rorw  $8,%%ax;"
                "rorl  $16,%0;"
                "rorw  $8,%%ax" : "=a" (lout) : "0" (value) );
#else
    __asm__ volatile( "bswap %0" : "=r"  (lout) : "0"   (value));
#endif
  return( lout );
}

static inline uint16_t i386_swap_u16(
  uint16_t value
)
{
  unsigned short      sout;

  __asm__ volatile( "rorw $8,%0" : "=r"  (sout) : "0"   (value));
  return (sout);
}

/*
 * Added for pagination management
 */
static inline unsigned int i386_get_cr0(void)
{
  register unsigned int segment = 0;

  __asm__ volatile ( "movl %%cr0,%0" : "=r" (segment) : "0" (segment) );

  return segment;
}

static inline void i386_set_cr0(unsigned int segment)
{
  __asm__ volatile ( "movl %0,%%cr0" : "=r" (segment) : "0" (segment) );
}

static inline unsigned int i386_get_cr2(void)
{
  register unsigned int segment = 0;

  __asm__ volatile ( "movl %%cr2,%0" : "=r" (segment) : "0" (segment) );

  return segment;
}

static inline unsigned int i386_get_cr3(void)
{
  register unsigned int segment = 0;

  __asm__ volatile ( "movl %%cr3,%0" : "=r" (segment) : "0" (segment) );

  return segment;
}

static inline void i386_set_cr3(unsigned int segment)
{
  __asm__ volatile ( "movl %0,%%cr3" : "=r" (segment) : "0" (segment) );
}

/* routines */

/*
 *  i386_Logical_to_physical
 *
 *  Converts logical address to physical address.
 */
void *i386_Logical_to_physical(
  unsigned short  segment,
  void           *address
);

/*
 *  i386_Physical_to_logical
 *
 *  Converts physical address to logical address.
 */
void *i386_Physical_to_logical(
  unsigned short  segment,
  void           *address
);

/*
 *  i386_Real_to_physical
 *
 *  Converts real mode pointer {segment, offset} to physical address.
 */
RTEMS_INLINE_ROUTINE void *i386_Real_to_physical(
    uint16_t segment,
    uint16_t offset)
{
    return (void *)(((uint32_t)segment<<4)+offset);
}

/*
 *  i386_Physical_to_real
 *  Retreives real mode pointer elements {segmnet, offset} from physical address
 *  Function returns the highest segment (base) address possible.
 *  Example:    input   address - 0x4B3A2
 *              output  segment - 0x4B3A
 *                      offset  - 0x2
 *              input   address - 0x10F12E
 *              output  segment - 0xFFFF
 *                      offset  - 0xF13E
 *
 *  return  0 address not convertible, must be less than 0x10FFEF
 *          1 segment and offset extracted
 */
int i386_Physical_to_real(
  void *address,
  uint16_t *segment,
  uint16_t *offset
);

/*
 *  "Simpler" names for a lot of the things defined in this file
 */

/* segment access routines */

#define get_cs()   i386_get_cs()
#define get_ds()   i386_get_ds()
#define get_es()   i386_get_es()
#define get_ss()   i386_get_ss()
#define get_fs()   i386_get_fs()
#define get_gs()   i386_get_gs()

#define CPU_swap_u32( _value )  i386_swap_u32( _value )
#define CPU_swap_u16( _value )  i386_swap_u16( _value )

/* i80x86 I/O instructions */

#define outport_byte( _port, _value ) i386_outport_byte( _port, _value )
#define outport_word( _port, _value ) i386_outport_word( _port, _value )
#define outport_long( _port, _value ) i386_outport_long( _port, _value )
#define inport_byte( _port, _value )  i386_inport_byte( _port, _value )
#define inport_word( _port, _value )  i386_inport_word( _port, _value )
#define inport_long( _port, _value )  i386_inport_long( _port, _value )


#ifdef __cplusplus
}
#endif

#endif /* !ASM */

#endif