source: rtems/cpukit/score/cpu/i386/cpu_asm.S @ d0279f6e

4.9
Last change on this file since d0279f6e was 84c53452, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/16/04 at 11:08:36

Remove stray white spaces.

  • Property mode set to 100644
File size: 7.9 KB
Line 
1/*  cpu_asm.s
2 *
3 *  This file contains all assembly code for the Intel i386 implementation
4 *  of RTEMS.
5 *
6 *  COPYRIGHT (c) 1989-1999.
7 *  On-Line Applications Research Corporation (OAR).
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.rtems.com/license/LICENSE.
12 *
13 *  $Id$
14 */
15
16#include <rtems/asm.h>
17
18/*
19 * Format of i386 Register structure
20 */
21
22.set REG_EFLAGS,  0
23.set REG_ESP,     REG_EFLAGS + 4
24.set REG_EBP,     REG_ESP + 4
25.set REG_EBX,     REG_EBP + 4
26.set REG_ESI,     REG_EBX + 4
27.set REG_EDI,     REG_ESI + 4
28.set SIZE_REGS,   REG_EDI + 4
29
30        BEGIN_CODE
31
32/*
33 *  void _CPU_Context_switch( run_context, heir_context )
34 *
35 *  This routine performs a normal non-FP context.
36 */
37
38        .p2align  1
39        PUBLIC (_CPU_Context_switch)
40
41.set RUNCONTEXT_ARG,   4                   /* save context argument */
42.set HEIRCONTEXT_ARG,  8                   /* restore context argument */
43
44SYM (_CPU_Context_switch):
45        movl      RUNCONTEXT_ARG(esp),eax  /* eax = running threads context */
46        pushf                              /* push eflags */
47        popl      REG_EFLAGS(eax)          /* save eflags */
48        movl      esp,REG_ESP(eax)         /* save stack pointer */
49        movl      ebp,REG_EBP(eax)         /* save base pointer */
50        movl      ebx,REG_EBX(eax)         /* save ebx */
51        movl      esi,REG_ESI(eax)         /* save source register */
52        movl      edi,REG_EDI(eax)         /* save destination register */
53
54        movl      HEIRCONTEXT_ARG(esp),eax /* eax = heir threads context */
55
56restore:
57        pushl     REG_EFLAGS(eax)          /* push eflags */
58        popf                               /* restore eflags */
59        movl      REG_ESP(eax),esp         /* restore stack pointer */
60        movl      REG_EBP(eax),ebp         /* restore base pointer */
61        movl      REG_EBX(eax),ebx         /* restore ebx */
62        movl      REG_ESI(eax),esi         /* restore source register */
63        movl      REG_EDI(eax),edi         /* restore destination register */
64        ret
65
66/*
67 *  NOTE: May be unnecessary to reload some registers.
68 */
69
70/*
71 *  void _CPU_Context_restore( new_context )
72 *
73 *  This routine performs a normal non-FP context.
74 */
75
76        PUBLIC (_CPU_Context_restore)
77
78.set NEWCONTEXT_ARG,   4                   /* context to restore argument */
79
80SYM (_CPU_Context_restore):
81
82        movl      NEWCONTEXT_ARG(esp),eax  /* eax = running threads context */
83        jmp       restore
84
85/*PAGE
86 *  void _CPU_Context_save_fp_context( &fp_context_ptr )
87 *  void _CPU_Context_restore_fp_context( &fp_context_ptr )
88 *
89 *  This section is used to context switch an i80287, i80387,
90 *  the built-in coprocessor or the i80486 or compatible.
91 */
92
93.set FPCONTEXT_ARG,   4                    /* FP context argument */
94
95        .p2align  1
96        PUBLIC (_CPU_Context_save_fp)
97SYM (_CPU_Context_save_fp):
98        movl      FPCONTEXT_ARG(esp),eax   /* eax = &ptr to FP context area */
99        movl      (eax),eax                /* eax = FP context area */
100        fsave     (eax)                    /* save FP context */
101        ret
102
103        .p2align  1
104        PUBLIC (_CPU_Context_restore_fp)
105SYM (_CPU_Context_restore_fp):
106        movl      FPCONTEXT_ARG(esp),eax   /* eax = &ptr to FP context area */
107        movl      (eax),eax                /* eax = FP context area */
108        frstor    (eax)                    /* restore FP context */
109        ret
110
111        PUBLIC (_Exception_Handler)
112SYM (_Exception_Handler):
113        pusha                              /* Push general purpose registers */
114        pushl   esp                        /* Push exception frame address */
115        movl    _currentExcHandler, eax    /* Call function storead in _currentExcHandler */
116        call    * eax
117        addl    $4, esp
118        popa                               /* restore general purpose registers */
119        addl    $8, esp                    /* skill vector number and faultCode */
120        iret
121
122#define DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY(_vector) \
123        .p2align 4                         ; \
124        PUBLIC (rtems_exception_prologue_ ## _vector ) ; \
125SYM (rtems_exception_prologue_ ## _vector ):             \
126        pushl   $ _vector       ; \
127        jmp   SYM (_Exception_Handler) ;
128
129#define DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY(_vector) \
130        .p2align 4                         ; \
131        PUBLIC (rtems_exception_prologue_ ## _vector ) ; \
132SYM (rtems_exception_prologue_ ## _vector ):             \
133        pushl   $ 0             ; \
134        pushl   $ _vector       ; \
135        jmp   SYM (_Exception_Handler) ;
136
137/*
138 * Divide Error
139 */
140DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (0)
141/*
142 * Debug Exception
143 */
144DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (1)
145/*
146 * NMI
147 */
148DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (2)
149/*
150 * Breakpoint
151 */
152DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (3)
153/*
154 * Overflow
155 */
156DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (4)
157/*
158 * Bound Range Exceeded
159 */
160DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (5)
161/*
162 * Invalid Opcode
163 */
164DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (6)
165/*
166 * No Math Coproc
167 */
168DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (7)
169/*
170 * Double Fault
171 */
172DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (8)
173/*
174 * Coprocessor segment overrun
175 */
176DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (9)
177/*
178 * Invalid TSS
179 */
180DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (10)
181/*
182 * Segment Not Present
183 */
184DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (11)
185/*
186 * Stack segment Fault
187 */
188DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (12)
189/*
190 * General Protection Fault
191 */
192DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (13)
193/*
194 * Page Fault
195 */
196DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (14)
197/*
198 * Floating point error (NB 15 is reserved it is therefor skipped)
199 */
200DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (16)
201/*
202 * Aligment Check
203 */
204DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (17)
205/*
206 * Machine Check
207 */
208DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (18)
209
210
211/*
212 *  void *i386_Logical_to_physical(
213 *     uint16_t    segment,
214 *     void             *address
215 *  );
216 *
217 *  Returns thirty-two bit physical address for segment:address.
218 */
219
220.set SEGMENT_ARG, 4
221.set ADDRESS_ARG, 8
222
223             PUBLIC (i386_Logical_to_physical)
224
225SYM (i386_Logical_to_physical):
226
227        xorl    eax,eax                /* clear eax */
228        movzwl  SEGMENT_ARG(esp),ecx   /* ecx = segment value */
229        movl    $ SYM (_Global_descriptor_table),edx
230                                       /* edx = address of our GDT */
231        addl    ecx,edx                /* edx = address of desired entry */
232        movb    7(edx),ah              /* ah = base 31:24 */
233        movb    4(edx),al              /* al = base 23:16 */
234        shll    $16,eax                /* move ax into correct bits */
235        movw    2(edx),ax              /* ax = base 0:15 */
236        movl    ADDRESS_ARG(esp),ecx   /* ecx = address to convert */
237        addl    eax,ecx                /* ecx = physical address equivalent */
238        movl    ecx,eax                /* eax = ecx */
239        ret
240
241/*
242 *  void *i386_Physical_to_logical(
243 *     uint16_t    segment,
244 *     void             *address
245 *  );
246 *
247 *  Returns thirty-two bit physical address for segment:address.
248 */
249
250/*
251 *.set SEGMENT_ARG, 4
252 *.set ADDRESS_ARG, 8   -- use sets from above
253 */
254
255       PUBLIC (i386_Physical_to_logical)
256
257SYM (i386_Physical_to_logical):
258        xorl    eax,eax                /* clear eax */
259        movzwl  SEGMENT_ARG(esp),ecx   /* ecx = segment value */
260        movl    $ SYM (_Global_descriptor_table),edx
261                                       /* edx = address of our GDT */
262        addl    ecx,edx                /* edx = address of desired entry */
263        movb    7(edx),ah              /* ah = base 31:24 */
264        movb    4(edx),al              /* al = base 23:16 */
265        shll    $16,eax                /* move ax into correct bits */
266        movw    2(edx),ax              /* ax = base 0:15 */
267        movl    ADDRESS_ARG(esp),ecx   /* ecx = address to convert */
268        subl    eax,ecx                /* ecx = logical address equivalent */
269        movl    ecx,eax                /* eax = ecx */
270        ret
271
272END_CODE
273
274END
Note: See TracBrowser for help on using the repository browser.