Add hidden_def.
[glibc.git] / sysdeps / standalone / i386 / start.S
blobd0037638da0111fc8ab7a8c21d5589d42f1dde12
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.
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.
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
21 /*  entry.s
22  *
23  *  This file contains the entry point for the application.
24  *  The name of this entry point is compiler dependent.
25  *  It jumps to the BSP which is responsible for performing
26  *  all initialization.
27  *
28  */
30         .data
31         .global  _Do_Load_IDT
32         .global  _Do_Load_GDT
34         .text
35               .global  start                  # GNU default entry point
36         .global  _establish_stack
38         .global   _bsp_start
39         .global   _load_segments
40         .global   __exit
42 start:
43         nop
44         cli                             # DISABLE INTERRUPTS!!!
46 #  Load the segment registers
48 #  NOTE: Upon return, gs will contain the segment descriptor for
49 #        a segment which maps directly to all of physical memory.
51         jmp     _load_segments          # load board dependent segments
54 #  Set up the stack
57 _establish_stack:
59         movl    $stack_end,%esp         # set stack pointer
60         movl    $stack_end,%ebp         # set base pointer
63 #  Zero out the BSS segment
65 zero_bss:
66         cld                             # make direction flag count up
67         movl    $_end,%ecx              # find end of .bss
68         movl    $_bss_start,%edi        # edi = beginning of .bss
69         subl    %edi,%ecx               # ecx = size of .bss in bytes
70         shrl    $2,%ecx                 # size of .bss in longs
71         xorl    %eax,%eax               # value to clear out memory
72         repne                           # while ecx != 0
73         stosl                           #   clear a long in the bss
76 #  Set the C heap information for malloc
78         movl    $heap_size,___C_heap_size    # set ___C_heap_size
79         movl    $heap_memory,___C_heap_start # set ___C_heap_start
82 #  Copy the Global Descriptor Table to our space
85         sgdt    _Original_GDTR          # save original GDT
86         movzwl  _Original_GDTR_limit,%ecx # size of GDT in bytes; limit
87                                           #   is 8192 entries * 8 bytes per
89         # make ds:esi point to the original GDT
91         movl    _Original_GDTR_base,%esi
92         push    %ds                     # save ds
93         movw    %gs,%ax
94         movw    %ax,%ds
96         # make es:edi point to the new (our copy) GDT
97         movl    $_Global_descriptor_table,%edi
99         rep
100         movsb                            # copy the GDT (ds:esi -> es:edi)
102         pop     %ds                      # restore ds
104         # Build and load new contents of GDTR
105         movw    _Original_GDTR_limit,%ecx # set new limit
106         movw    %cx,_New_GDTR_limit
108         push    $_Global_descriptor_table
109         push    %es
110         call    _Logical_to_physical
111         addl    $6,%esp
112         movl    %eax,_New_GDTR_base      # set new base
114         cmpb    $0,_Do_Load_GDT          # Should the new GDT be loaded?
115         je      no_gdt_load              # NO, then branch
116         lgdt    _New_GDTR                # load the new GDT
117 no_gdt_load:
120 #  Copy the Interrupt Descriptor Table to our space
123         sidt    _Original_IDTR          # save original IDT
124         movzwl  _Original_IDTR_limit,%ecx # size of IDT in bytes; limit
125                                           #   is 256 entries * 8 bytes per
128         # make ds:esi point to the original IDT
129         movl    _Original_IDTR_base,%esi
131         push    %ds                     # save ds
132         movw    %gs,%ax
133         movw    %ax,%ds
135         # make es:edi point to the new (our copy) IDT
136         movl    $_Interrupt_descriptor_table,%edi
138         rep
139         movsb                            # copy the IDT (ds:esi -> es:edi)
140         pop     %ds                      # restore ds
142         # Build and load new contents of IDTR
143         movw    _Original_IDTR_limit,%ecx # set new limit
144         movw    %cx,_New_IDTR_limit
146         push    $_Interrupt_descriptor_table
147         push    %es
148         call    _Logical_to_physical
149         addl    $6,%esp
150         movl    %eax,_New_IDTR_base      # set new base
152         cmpb    $0,_Do_Load_IDT          # Should the new IDT be loaded?
153         je      no_idt_load              # NO, then branch
154         lidt    _New_IDTR                # load the new IDT
155 no_idt_load:
158 #  Initialize the i387.
160 #  Using the NO WAIT form of the instruction insures that if
161 #  it is not present the board will not lock up or get an
162 #  exception.
165         fninit                           # MUST USE NO-WAIT FORM
167         call    __Board_Initialize       # initialize the board
169         pushl   $0                       # envp = NULL
170         pushl   $0                       # argv = NULL
171         pushl   $0                       # argc = NULL
172         call    ___libc_init             # initialize the library and
173                                          #   call main
174         addl    $12,%esp
176         pushl   $0                       # argc = NULL
177         call    __exit                   # call the Board specific exit
178         addl     $4,%esp
181 #  Clean up
185         .global  _Bsp_cleanup
187         .global   _return_to_monitor
189 _Bsp_cleanup:
190         cmpb    $0,_Do_Load_IDT          # Was the new IDT loaded?
191         je      no_idt_restore           # NO, then branch
192         lidt    _Original_IDTR           # restore the new IDT
193 no_idt_restore:
195         cmpb    $0,_Do_Load_GDT          # Was the new GDT loaded?
196         je      no_gdt_restore           # NO, then branch
197         lgdt    _Original_GDTR           # restore the new GDT
198 no_gdt_restore:
199         jmp     _return_to_monitor
202 #  void *Logical_to_physical(
203 #     rtems_unsigned16  segment,
204 #     void             *address
205 #  );
207 #  Returns thirty-two bit physical address for segment:address.
210         .global  _Logical_to_physical
212 .set SEGMENT_ARG, 4
213 .set ADDRESS_ARG, 8
215 _Logical_to_physical:
217         xorl    %eax,%eax                # clear eax
218         movzwl  SEGMENT_ARG(%esp),%ecx   # ecx = segment value
219         movl    $_Global_descriptor_table,%edx # edx = address of our GDT
220         addl    %ecx,%edx                # edx = address of desired entry
221         movb    7(%edx),%ah              # ah = base 31:24
222         movb    4(%edx),%al              # al = base 23:16
223         shll    $16,%eax                 # move ax into correct bits
224         movw    2(%edx),%ax              # ax = base 0:15
225         movl    ADDRESS_ARG(%esp),%ecx   # ecx = address to convert
226         addl    %eax,%ecx                # ecx = physical address equivalent
227         movl    %ecx,%eax                # eax = ecx
228         ret
231 #  void *Physical_to_logical(
232 #     rtems_unsigned16  segment,
233 #     void             *address
234 #  );
236 #  Returns thirty-two bit physical address for segment:address.
239         .global  _Physical_to_logical
241 #.set SEGMENT_ARG, 4
242 #.set ADDRESS_ARG, 8   -- use sets from above
244 _Physical_to_logical:
246         xorl    %eax,%eax                # clear eax
247         movzwl  SEGMENT_ARG(%esp),%ecx   # ecx = segment value
248         movl    $_Global_descriptor_table,%edx # edx = address of our GDT
249         addl    %ecx,%edx                # edx = address of desired entry
250         movb    7(%edx),%ah              # ah = base 31:24
251         movb    4(%edx),%al              # al = base 23:16
252         shll    $16,%eax                 # move ax into correct bits
253         movw    2(%edx),%ax              # ax = base 0:15
254         movl    ADDRESS_ARG(%esp),%ecx   # ecx = address to convert
255         subl    %eax,%ecx                # ecx = logical address equivalent
256         movl    %ecx,%eax                # eax = ecx
257         ret
261  *  Data Declarations.  Start with a macro which helps declare space.
262  */
264         .bss
266 #define DECLARE_SPACE(_name,_space,_align) \
267           .globl   _name ; \
268           .align   _align ; \
269 _name##:  .space _space
271 #define DECLARE_LABEL(_name) \
272           .globl   _name ; \
273 _name##:
275 #define DECLARE_PTR(_name) DECLARE_SPACE(_name,4,2)
276 #define DECLARE_U32(_name) DECLARE_SPACE(_name,4,2)
277 #define DECLARE_U16(_name) DECLARE_SPACE(_name,2,1)
280  *  Require environment stuff
281  */
283 DECLARE_LABEL(_environ)
284 DECLARE_PTR(environ)
286 DECLARE_LABEL(_errno)
287 DECLARE_U32(errno)
290  *  Miscellaneous Variables used to restore the CPU state.
292  *  Start with a macro to declare the space for the contents of
293  *  a Descriptor Table register.
294  */
296 #define DECLARE_DTR_SPACE(_name) \
297           .global   _name ; \
298           .align    4 ; \
299 _name##:  ; \
300 _name##_limit:  .space 2  ; \
301 _name##_base:   .space 4
303 DECLARE_SPACE(_Interrupt_descriptor_table,256*8,4)
304 DECLARE_SPACE(_Global_descriptor_table,8192*8,4)
306 DECLARE_DTR_SPACE(_Original_IDTR)
307 DECLARE_DTR_SPACE(_New_IDTR)
308 DECLARE_DTR_SPACE(_Original_GDTR)
309 DECLARE_DTR_SPACE(_New_GDTR)
311 DECLARE_SPACE(_Physical_base_of_ds,4,4)
312 DECLARE_SPACE(_Physical_base_of_cs,4,4)
315  *  Stack Size and Space
316  */
318         .set stack_size, 0x20000
320 DECLARE_SPACE(stack_memory,stack_size,4)
321 DECLARE_LABEL(stack_end)