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

4.115
Last change on this file since 038e1dba was 038e1dba, checked in by Jan Dolezal <dolezj21@…>, on Dec 3, 2014 at 11:56:39 PM

i386: doxygen and comments related to VESA real mode framebuffer

  • Property mode set to 100644
File size: 10.8 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.org/license/LICENSE.
12 */
13
14#ifdef HAVE_CONFIG_H
15#include "config.h"
16#endif
17
18#include <rtems/asm.h>
19#include <rtems/score/cpu.h>
20
21#ifndef CPU_STACK_ALIGNMENT
22#error "Missing header? CPU_STACK_ALIGNMENT not defined"
23#endif
24
25/*
26 * Format of i386 Register structure
27 */
28
29.set REG_EFLAGS,  I386_CONTEXT_CONTROL_EFLAGS_OFFSET
30.set REG_ESP,     I386_CONTEXT_CONTROL_ESP_OFFSET
31.set REG_EBP,     I386_CONTEXT_CONTROL_EBP_OFFSET
32.set REG_EBX,     I386_CONTEXT_CONTROL_EBX_OFFSET
33.set REG_ESI,     I386_CONTEXT_CONTROL_ESI_OFFSET
34.set REG_EDI,     I386_CONTEXT_CONTROL_EDI_OFFSET
35
36        BEGIN_CODE
37
38/*
39 *  void _CPU_Context_switch( run_context, heir_context )
40 *
41 *  This routine performs a normal non-FP context.
42 */
43
44        .p2align  1
45        PUBLIC (_CPU_Context_switch)
46
47.set RUNCONTEXT_ARG,   4                   /* save context argument */
48.set HEIRCONTEXT_ARG,  8                   /* restore context argument */
49
50SYM (_CPU_Context_switch):
51        movl      RUNCONTEXT_ARG(esp),eax  /* eax = running threads context */
52        pushf                              /* push eflags */
53        popl      REG_EFLAGS(eax)          /* save eflags */
54        movl      esp,REG_ESP(eax)         /* save stack pointer */
55        movl      ebp,REG_EBP(eax)         /* save base pointer */
56        movl      ebx,REG_EBX(eax)         /* save ebx */
57        movl      esi,REG_ESI(eax)         /* save source register */
58        movl      edi,REG_EDI(eax)         /* save destination register */
59
60#ifdef RTEMS_SMP
61        /* The executing context no longer executes on this processor */
62        movb      $0, I386_CONTEXT_CONTROL_IS_EXECUTING_OFFSET(eax)
63#endif
64
65        movl      HEIRCONTEXT_ARG(esp),eax /* eax = heir threads context */
66
67#ifdef RTEMS_SMP
68        /* Wait for heir context to stop execution */
691:
70        movb      I386_CONTEXT_CONTROL_IS_EXECUTING_OFFSET(eax), bl
71        testb     bl, bl
72        jne       1b
73
74        /* The heir context executes now on this processor */
75        movb      $1, I386_CONTEXT_CONTROL_IS_EXECUTING_OFFSET(eax)
76#endif
77
78restore:
79        pushl     REG_EFLAGS(eax)          /* push eflags */
80        popf                               /* restore eflags */
81        movl      REG_ESP(eax),esp         /* restore stack pointer */
82        movl      REG_EBP(eax),ebp         /* restore base pointer */
83        movl      REG_EBX(eax),ebx         /* restore ebx */
84        movl      REG_ESI(eax),esi         /* restore source register */
85        movl      REG_EDI(eax),edi         /* restore destination register */
86        ret
87
88/*
89 *  NOTE: May be unnecessary to reload some registers.
90 */
91
92/*
93 *  void _CPU_Context_restore( new_context )
94 *
95 *  This routine performs a normal non-FP context.
96 */
97
98        PUBLIC (_CPU_Context_restore)
99
100.set NEWCONTEXT_ARG,   4                   /* context to restore argument */
101
102SYM (_CPU_Context_restore):
103        movl      NEWCONTEXT_ARG(esp),eax  /* eax = running threads context */
104        jmp       restore
105
106/*void _CPU_Context_save_fp_context( &fp_context_ptr )
107 *  void _CPU_Context_restore_fp_context( &fp_context_ptr )
108 *
109 *  This section is used to context switch an i80287, i80387,
110 *  the built-in coprocessor or the i80486 or compatible.
111 */
112
113.set FPCONTEXT_ARG,   4                    /* FP context argument */
114
115#ifndef __SSE__
116        .p2align  1
117        PUBLIC (_CPU_Context_save_fp)
118SYM (_CPU_Context_save_fp):
119        movl      FPCONTEXT_ARG(esp),eax   /* eax = &ptr to FP context area */
120        movl      (eax),eax                /* eax = FP context area */
121        fsave     (eax)                    /* save FP context */
122        ret
123
124        .p2align  1
125        PUBLIC (_CPU_Context_restore_fp)
126SYM (_CPU_Context_restore_fp):
127        movl      FPCONTEXT_ARG(esp),eax   /* eax = &ptr to FP context area */
128        movl      (eax),eax                /* eax = FP context area */
129        frstor    (eax)                    /* restore FP context */
130        ret
131#endif
132
133#ifdef __SSE__
134#define SSE_OFF  16
135#endif
136
137        PUBLIC (_Exception_Handler)
138SYM (_Exception_Handler):
139        pusha                  /* Push general purpose registers    */
140        pushl   $0             /* Null pointer to SSE area          */
141        movl    esp,  ebp      /* Save original SP                  */
142#ifndef __SSE__
143        subl    $4,   esp      /* Reserve space for argument        */
144                           /* Align stack (courtesy for C/gcc)  */
145        andl    $ - CPU_STACK_ALIGNMENT, esp
146#else
147        subl    $512, esp      /* Space for SSE area                */
148                           /* Align stack (courtesy for C/gcc)  */
149        andl    $ - CPU_STACK_ALIGNMENT, esp
150/* Doing fwait here will re-throw an already pending FP exception!
151        fwait
152 */
153        fxsave  0(esp)
154        fninit                 /* Clean-slate FPU                   */
155        movl    $0x1f80, 0(ebp)
156        ldmxcsr 0(ebp)         /* Clean-slate MXCSR                 */
157        movl    esp, 0(ebp)    /* Store pointer to SSE area         */
158        subl    $SSE_OFF, esp  /* Aligned space for argument        */
159#endif
160        movl    ebp, (esp)     /* Store argument                    */
161        movl    _currentExcHandler, eax    /* Call function stored in _currentExcHandler */
162        call    * eax
163#ifdef __SSE__
164        fwait
165        fxrstor 16(esp)
166#endif
167        movl    ebp,  esp      /* Restore original SP               */
168        addl    $4,   esp      /* Skill pointer to SSE area         */
169        popa                   /* Restore general purpose registers */
170        addl    $8, esp        /* Skill vector number and faultCode */
171        iret
172
173#define DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY(_vector) \
174        .p2align 4                         ; \
175        PUBLIC (rtems_exception_prologue_ ## _vector ) ; \
176SYM (rtems_exception_prologue_ ## _vector ):             \
177        pushl   $ _vector       ; \
178        jmp   SYM (_Exception_Handler) ;
179
180#define DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY(_vector) \
181        .p2align 4                         ; \
182        PUBLIC (rtems_exception_prologue_ ## _vector ) ; \
183SYM (rtems_exception_prologue_ ## _vector ):             \
184        pushl   $ 0             ; \
185        pushl   $ _vector       ; \
186        jmp   SYM (_Exception_Handler) ;
187
188/*
189 * Divide Error
190 */
191DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (0)
192/*
193 * Debug Exception
194 */
195DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (1)
196/*
197 * NMI
198 */
199DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (2)
200/*
201 * Breakpoint
202 */
203DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (3)
204/*
205 * Overflow
206 */
207DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (4)
208/*
209 * Bound Range Exceeded
210 */
211DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (5)
212/*
213 * Invalid Opcode
214 */
215DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (6)
216/*
217 * No Math Coproc
218 */
219DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (7)
220/*
221 * Double Fault
222 */
223DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (8)
224/*
225 * Coprocessor segment overrun
226 */
227DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (9)
228/*
229 * Invalid TSS
230 */
231DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (10)
232/*
233 * Segment Not Present
234 */
235DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (11)
236/*
237 * Stack segment Fault
238 */
239DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (12)
240/*
241 * General Protection Fault
242 */
243DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (13)
244/*
245 * Page Fault
246 */
247DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (14)
248/*
249 * Floating point error (NB 15 is reserved it is therefor skipped)
250 */
251DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (16)
252/*
253 * Aligment Check
254 */
255DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (17)
256/*
257 * Machine Check
258 */
259DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (18)
260
261#ifdef __SSE__
262/*
263 * SIMD FP Exception
264 */
265DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (19)
266#endif
267
268
269/*
270 *  void *i386_Logical_to_physical(
271 *     uint16_t    segment,
272 *     void             *address
273 *  );
274 *
275 *  Returns thirty-two bit physical address for segment:address.
276 */
277
278.set SEGMENT_ARG, 4
279.set ADDRESS_ARG, 8
280
281             PUBLIC (i386_Logical_to_physical)
282
283SYM (i386_Logical_to_physical):
284
285        xorl    eax,eax                /* clear eax */
286        movzwl  SEGMENT_ARG(esp),ecx   /* ecx = segment value */
287        movl    $ SYM (_Global_descriptor_table),edx
288                                       /* edx = address of our GDT */
289        addl    ecx,edx                /* edx = address of desired entry */
290        movb    7(edx),ah              /* ah = base 31:24 */
291        movb    4(edx),al              /* al = base 23:16 */
292        shll    $16,eax                /* move ax into correct bits */
293        movw    2(edx),ax              /* ax = base 0:15 */
294        movl    ADDRESS_ARG(esp),ecx   /* ecx = address to convert */
295        addl    eax,ecx                /* ecx = physical address equivalent */
296        movl    ecx,eax                /* eax = ecx */
297        ret
298
299/*
300 *  void *i386_Physical_to_logical(
301 *     uint16_t    segment,
302 *     void             *address
303 *  );
304 *
305 *  Returns thirty-two bit physical address for segment:address.
306 */
307
308/*
309 *.set SEGMENT_ARG, 4
310 *.set ADDRESS_ARG, 8   -- use sets from above
311 */
312
313       PUBLIC (i386_Physical_to_logical)
314
315SYM (i386_Physical_to_logical):
316        xorl    eax,eax                /* clear eax */
317        movzwl  SEGMENT_ARG(esp),ecx   /* ecx = segment value */
318        movl    $ SYM (_Global_descriptor_table),edx
319                                       /* edx = address of our GDT */
320        addl    ecx,edx                /* edx = address of desired entry */
321        movb    7(edx),ah              /* ah = base 31:24 */
322        movb    4(edx),al              /* al = base 23:16 */
323        shll    $16,eax                /* move ax into correct bits */
324        movw    2(edx),ax              /* ax = base 0:15 */
325        movl    ADDRESS_ARG(esp),ecx   /* ecx = address to convert */
326        subl    eax,ecx                /* ecx = logical address equivalent */
327        movl    ecx,eax                /* eax = ecx */
328        ret
329
330/*
331 *  int i386_Physical_to_real(
332 *     void     *address,
333 *     uint16_t *segment,
334 *     uint16_t *offset
335 *  );
336 *
337 *  Fills segment:offest real mode pointer counted from thirty-two bit physical
338 *  address.
339 *  Returns 0 if inconvertible, 1 if successfuly converted.
340 */
341
342.set PHYS_PTR_ARG,   4
343.set RM_PTR_SEG_ARG, 8
344.set RM_PTR_OFF_ARG, 12
345
346       PUBLIC (i386_Physical_to_real)
347
348SYM (i386_Physical_to_real):
349        movl    PHYS_PTR_ARG(esp),eax
350        cmpl    $0x10FFF0, eax
351        js      1f
352        movl    $0, eax
353        ret
3541:      cmpl    $0x100000, eax
355        js      2f
356        subl    $0xFFFF0, eax
357        movl    RM_PTR_OFF_ARG(esp), ecx
358        movw    ax, (ecx)
359        movl    RM_PTR_SEG_ARG(esp), ecx
360        movw    $0xFFFF, (ecx)
361        movl    $1, eax
362        ret
3632:      movl    eax, edx
364        and     $0xF, ax
365        movl    RM_PTR_OFF_ARG(esp), ecx
366        movw    ax, (ecx)
367        shrl    $4, edx
368        movl    RM_PTR_SEG_ARG(esp), ecx
369        movw    dx, (ecx)
370        movl    $1, eax
371        ret
372
373END_CODE
374
375END
Note: See TracBrowser for help on using the repository browser.