~ubuntu-branches/ubuntu/precise/eglibc/precise-201308281639

« back to all changes in this revision

Viewing changes to ports/sysdeps/standalone/i386/start.S

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2012-02-08 01:58:09 UTC
  • mfrom: (1.5.3) (288.1.12 precise)
  • Revision ID: package-import@ubuntu.com-20120208015809-ulscst7uteq3e22z
Tags: 2.15~pre6-0ubuntu10
Merge from Debian (r5151, 2.13-26).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 1994, 1997 Free Software Foundation, Inc.
2
 
   Contributed by Joel Sherrill (jsherril@redstone-emh2.army.mil),
3
 
     On-Line Applications Research Corporation.
4
 
   This file is part of the GNU C Library.
5
 
 
6
 
   The GNU C Library is free software; you can redistribute it and/or
7
 
   modify it under the terms of the GNU Lesser General Public
8
 
   License as published by the Free Software Foundation; either
9
 
   version 2.1 of the License, or (at your option) any later version.
10
 
 
11
 
   In addition to the permissions in the GNU Lesser General Public
12
 
   License, the Free Software Foundation gives you unlimited
13
 
   permission to link the compiled version of this file with other
14
 
   programs, and to distribute those programs without any restriction
15
 
   coming from the use of this file. (The GNU Lesser General Public
16
 
   License restrictions do apply in other respects; for example, they
17
 
   cover modification of the file, and distribution when not linked
18
 
   into another program.)
19
 
 
20
 
   Note that people who make modified versions of this file are not
21
 
   obligated to grant this special exception for their modified
22
 
   versions; it is their choice whether to do so. The GNU Lesser
23
 
   General Public License gives permission to release a modified
24
 
   version without this exception; this exception also makes it
25
 
   possible to release a modified version which carries forward this
26
 
   exception.
27
 
 
28
 
   The GNU C Library is distributed in the hope that it will be useful,
29
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
30
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
31
 
   Lesser General Public License for more details.
32
 
 
33
 
   You should have received a copy of the GNU Lesser General Public
34
 
   License along with the GNU C Library; if not, write to the Free
35
 
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
36
 
   02111-1307 USA.  */
37
 
 
38
 
/*  entry.s
39
 
 *
40
 
 *  This file contains the entry point for the application.
41
 
 *  The name of this entry point is compiler dependent.
42
 
 *  It jumps to the BSP which is responsible for performing
43
 
 *  all initialization.
44
 
 *
45
 
 */
46
 
 
47
 
        .data
48
 
        .global  _Do_Load_IDT
49
 
        .global  _Do_Load_GDT
50
 
 
51
 
        .text
52
 
              .global  start                  # GNU default entry point
53
 
        .global  _establish_stack
54
 
 
55
 
        .global   _bsp_start
56
 
        .global   _load_segments
57
 
        .global   __exit
58
 
 
59
 
start:
60
 
        nop
61
 
        cli                             # DISABLE INTERRUPTS!!!
62
 
#
63
 
#  Load the segment registers
64
 
#
65
 
#  NOTE: Upon return, gs will contain the segment descriptor for
66
 
#        a segment which maps directly to all of physical memory.
67
 
#
68
 
        jmp     _load_segments          # load board dependent segments
69
 
 
70
 
#
71
 
#  Set up the stack
72
 
#
73
 
 
74
 
_establish_stack:
75
 
 
76
 
        movl    $stack_end,%esp         # set stack pointer
77
 
        movl    $stack_end,%ebp         # set base pointer
78
 
 
79
 
#
80
 
#  Zero out the BSS segment
81
 
#
82
 
zero_bss:
83
 
        cld                             # make direction flag count up
84
 
        movl    $_end,%ecx              # find end of .bss
85
 
        movl    $_bss_start,%edi        # edi = beginning of .bss
86
 
        subl    %edi,%ecx               # ecx = size of .bss in bytes
87
 
        shrl    $2,%ecx                 # size of .bss in longs
88
 
        xorl    %eax,%eax               # value to clear out memory
89
 
        repne                           # while ecx != 0
90
 
        stosl                           #   clear a long in the bss
91
 
 
92
 
#
93
 
#  Set the C heap information for malloc
94
 
#
95
 
        movl    $heap_size,___C_heap_size    # set ___C_heap_size
96
 
        movl    $heap_memory,___C_heap_start # set ___C_heap_start
97
 
 
98
 
#
99
 
#  Copy the Global Descriptor Table to our space
100
 
#
101
 
 
102
 
        sgdt    _Original_GDTR          # save original GDT
103
 
        movzwl  _Original_GDTR_limit,%ecx # size of GDT in bytes; limit
104
 
                                          #   is 8192 entries * 8 bytes per
105
 
 
106
 
        # make ds:esi point to the original GDT
107
 
 
108
 
        movl    _Original_GDTR_base,%esi
109
 
        push    %ds                     # save ds
110
 
        movw    %gs,%ax
111
 
        movw    %ax,%ds
112
 
 
113
 
        # make es:edi point to the new (our copy) GDT
114
 
        movl    $_Global_descriptor_table,%edi
115
 
 
116
 
        rep
117
 
        movsb                            # copy the GDT (ds:esi -> es:edi)
118
 
 
119
 
        pop     %ds                      # restore ds
120
 
 
121
 
        # Build and load new contents of GDTR
122
 
        movw    _Original_GDTR_limit,%ecx # set new limit
123
 
        movw    %cx,_New_GDTR_limit
124
 
 
125
 
        push    $_Global_descriptor_table
126
 
        push    %es
127
 
        call    _Logical_to_physical
128
 
        addl    $6,%esp
129
 
        movl    %eax,_New_GDTR_base      # set new base
130
 
 
131
 
        cmpb    $0,_Do_Load_GDT          # Should the new GDT be loaded?
132
 
        je      no_gdt_load              # NO, then branch
133
 
        lgdt    _New_GDTR                # load the new GDT
134
 
no_gdt_load:
135
 
 
136
 
#
137
 
#  Copy the Interrupt Descriptor Table to our space
138
 
#
139
 
 
140
 
        sidt    _Original_IDTR          # save original IDT
141
 
        movzwl  _Original_IDTR_limit,%ecx # size of IDT in bytes; limit
142
 
                                          #   is 256 entries * 8 bytes per
143
 
 
144
 
 
145
 
        # make ds:esi point to the original IDT
146
 
        movl    _Original_IDTR_base,%esi
147
 
 
148
 
        push    %ds                     # save ds
149
 
        movw    %gs,%ax
150
 
        movw    %ax,%ds
151
 
 
152
 
        # make es:edi point to the new (our copy) IDT
153
 
        movl    $_Interrupt_descriptor_table,%edi
154
 
 
155
 
        rep
156
 
        movsb                            # copy the IDT (ds:esi -> es:edi)
157
 
        pop     %ds                      # restore ds
158
 
 
159
 
        # Build and load new contents of IDTR
160
 
        movw    _Original_IDTR_limit,%ecx # set new limit
161
 
        movw    %cx,_New_IDTR_limit
162
 
 
163
 
        push    $_Interrupt_descriptor_table
164
 
        push    %es
165
 
        call    _Logical_to_physical
166
 
        addl    $6,%esp
167
 
        movl    %eax,_New_IDTR_base      # set new base
168
 
 
169
 
        cmpb    $0,_Do_Load_IDT          # Should the new IDT be loaded?
170
 
        je      no_idt_load              # NO, then branch
171
 
        lidt    _New_IDTR                # load the new IDT
172
 
no_idt_load:
173
 
 
174
 
#
175
 
#  Initialize the i387.
176
 
#
177
 
#  Using the NO WAIT form of the instruction insures that if
178
 
#  it is not present the board will not lock up or get an
179
 
#  exception.
180
 
#
181
 
 
182
 
        fninit                           # MUST USE NO-WAIT FORM
183
 
 
184
 
        call    __Board_Initialize       # initialize the board
185
 
 
186
 
        pushl   $0                       # envp = NULL
187
 
        pushl   $0                       # argv = NULL
188
 
        pushl   $0                       # argc = NULL
189
 
        call    ___libc_init             # initialize the library and
190
 
                                         #   call main
191
 
        addl    $12,%esp
192
 
 
193
 
        pushl   $0                       # argc = NULL
194
 
        call    __exit                   # call the Board specific exit
195
 
        addl     $4,%esp
196
 
 
197
 
#
198
 
#  Clean up
199
 
#
200
 
 
201
 
 
202
 
        .global  _Bsp_cleanup
203
 
 
204
 
        .global   _return_to_monitor
205
 
 
206
 
_Bsp_cleanup:
207
 
        cmpb    $0,_Do_Load_IDT          # Was the new IDT loaded?
208
 
        je      no_idt_restore           # NO, then branch
209
 
        lidt    _Original_IDTR           # restore the new IDT
210
 
no_idt_restore:
211
 
 
212
 
        cmpb    $0,_Do_Load_GDT          # Was the new GDT loaded?
213
 
        je      no_gdt_restore           # NO, then branch
214
 
        lgdt    _Original_GDTR           # restore the new GDT
215
 
no_gdt_restore:
216
 
        jmp     _return_to_monitor
217
 
 
218
 
#
219
 
#  void *Logical_to_physical(
220
 
#     rtems_unsigned16  segment,
221
 
#     void             *address
222
 
#  );
223
 
#
224
 
#  Returns thirty-two bit physical address for segment:address.
225
 
#
226
 
 
227
 
        .global  _Logical_to_physical
228
 
 
229
 
.set SEGMENT_ARG, 4
230
 
.set ADDRESS_ARG, 8
231
 
 
232
 
_Logical_to_physical:
233
 
 
234
 
        xorl    %eax,%eax                # clear eax
235
 
        movzwl  SEGMENT_ARG(%esp),%ecx   # ecx = segment value
236
 
        movl    $_Global_descriptor_table,%edx # edx = address of our GDT
237
 
        addl    %ecx,%edx                # edx = address of desired entry
238
 
        movb    7(%edx),%ah              # ah = base 31:24
239
 
        movb    4(%edx),%al              # al = base 23:16
240
 
        shll    $16,%eax                 # move ax into correct bits
241
 
        movw    2(%edx),%ax              # ax = base 0:15
242
 
        movl    ADDRESS_ARG(%esp),%ecx   # ecx = address to convert
243
 
        addl    %eax,%ecx                # ecx = physical address equivalent
244
 
        movl    %ecx,%eax                # eax = ecx
245
 
        ret
246
 
 
247
 
#
248
 
#  void *Physical_to_logical(
249
 
#     rtems_unsigned16  segment,
250
 
#     void             *address
251
 
#  );
252
 
#
253
 
#  Returns thirty-two bit physical address for segment:address.
254
 
#
255
 
 
256
 
        .global  _Physical_to_logical
257
 
 
258
 
#.set SEGMENT_ARG, 4
259
 
#.set ADDRESS_ARG, 8   -- use sets from above
260
 
 
261
 
_Physical_to_logical:
262
 
 
263
 
        xorl    %eax,%eax                # clear eax
264
 
        movzwl  SEGMENT_ARG(%esp),%ecx   # ecx = segment value
265
 
        movl    $_Global_descriptor_table,%edx # edx = address of our GDT
266
 
        addl    %ecx,%edx                # edx = address of desired entry
267
 
        movb    7(%edx),%ah              # ah = base 31:24
268
 
        movb    4(%edx),%al              # al = base 23:16
269
 
        shll    $16,%eax                 # move ax into correct bits
270
 
        movw    2(%edx),%ax              # ax = base 0:15
271
 
        movl    ADDRESS_ARG(%esp),%ecx   # ecx = address to convert
272
 
        subl    %eax,%ecx                # ecx = logical address equivalent
273
 
        movl    %ecx,%eax                # eax = ecx
274
 
        ret
275
 
 
276
 
 
277
 
/*
278
 
 *  Data Declarations.  Start with a macro which helps declare space.
279
 
 */
280
 
 
281
 
        .bss
282
 
 
283
 
#define DECLARE_SPACE(_name,_space,_align) \
284
 
          .globl   _name ; \
285
 
          .align   _align ; \
286
 
_name##:  .space _space
287
 
 
288
 
#define DECLARE_LABEL(_name) \
289
 
          .globl   _name ; \
290
 
_name##:
291
 
 
292
 
#define DECLARE_PTR(_name) DECLARE_SPACE(_name,4,2)
293
 
#define DECLARE_U32(_name) DECLARE_SPACE(_name,4,2)
294
 
#define DECLARE_U16(_name) DECLARE_SPACE(_name,2,1)
295
 
 
296
 
/*
297
 
 *  Require environment stuff
298
 
 */
299
 
 
300
 
DECLARE_LABEL(_environ)
301
 
DECLARE_PTR(environ)
302
 
 
303
 
DECLARE_LABEL(_errno)
304
 
DECLARE_U32(errno)
305
 
 
306
 
/*
307
 
 *  Miscellaneous Variables used to restore the CPU state.
308
 
 *
309
 
 *  Start with a macro to declare the space for the contents of
310
 
 *  a Descriptor Table register.
311
 
 */
312
 
 
313
 
#define DECLARE_DTR_SPACE(_name) \
314
 
          .global   _name ; \
315
 
          .align    4 ; \
316
 
_name##:  ; \
317
 
_name##_limit:  .space 2  ; \
318
 
_name##_base:   .space 4
319
 
 
320
 
DECLARE_SPACE(_Interrupt_descriptor_table,256*8,4)
321
 
DECLARE_SPACE(_Global_descriptor_table,8192*8,4)
322
 
 
323
 
DECLARE_DTR_SPACE(_Original_IDTR)
324
 
DECLARE_DTR_SPACE(_New_IDTR)
325
 
DECLARE_DTR_SPACE(_Original_GDTR)
326
 
DECLARE_DTR_SPACE(_New_GDTR)
327
 
 
328
 
DECLARE_SPACE(_Physical_base_of_ds,4,4)
329
 
DECLARE_SPACE(_Physical_base_of_cs,4,4)
330
 
 
331
 
/*
332
 
 *  Stack Size and Space
333
 
 */
334
 
 
335
 
        .set stack_size, 0x20000
336
 
 
337
 
DECLARE_SPACE(stack_memory,stack_size,4)
338
 
DECLARE_LABEL(stack_end)