1 /* Copyright (C) 1994 Free Software Foundation, Inc.
2 Contributed by Joel Sherrill (jsherril@redstone-emh2.army.mil),
3 On-Line Applications Research Corporation.
5 This file is part of the GNU C Library.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with the GNU C Library; see the file COPYING.LIB. If
19 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
20 Cambridge, MA 02139, USA. */
24 * This file contains the entry point for the application.
25 * The name of this entry point is compiler dependent.
26 * It jumps to the BSP which is responsible for performing
36 .global start # GNU default entry point
37 .global _establish_stack
40 .global _load_segments
45 cli # DISABLE INTERRUPTS!!!
47 # Load the segment registers
49 # NOTE: Upon return, gs will contain the segment descriptor for
50 # a segment which maps directly to all of physical memory.
52 jmp _load_segments # load board dependent segments
60 movl $stack_end,%esp # set stack pointer
61 movl $stack_end,%ebp # set base pointer
64 # Zero out the BSS segment
67 cld # make direction flag count up
68 movl $_end,%ecx # find end of .bss
69 movl $_bss_start,%edi # edi = beginning of .bss
70 subl %edi,%ecx # ecx = size of .bss in bytes
71 shrl $2,%ecx # size of .bss in longs
72 xorl %eax,%eax # value to clear out memory
73 repne # while ecx != 0
74 stosl # clear a long in the bss
77 # Set the C heap information for malloc
79 movl $heap_size,___C_heap_size # set ___C_heap_size
80 movl $heap_memory,___C_heap_start # set ___C_heap_start
83 # Copy the Global Descriptor Table to our space
86 sgdt _Original_GDTR # save original GDT
87 movzwl _Original_GDTR_limit,%ecx # size of GDT in bytes; limit
88 # is 8192 entries * 8 bytes per
90 # make ds:esi point to the original GDT
92 movl _Original_GDTR_base,%esi
97 # make es:edi point to the new (our copy) GDT
98 movl $_Global_descriptor_table,%edi
101 movsb # copy the GDT (ds:esi -> es:edi)
105 # Build and load new contents of GDTR
106 movw _Original_GDTR_limit,%ecx # set new limit
107 movw %cx,_New_GDTR_limit
109 push $_Global_descriptor_table
111 call _Logical_to_physical
113 movl %eax,_New_GDTR_base # set new base
115 cmpb $0,_Do_Load_GDT # Should the new GDT be loaded?
116 je no_gdt_load # NO, then branch
117 lgdt _New_GDTR # load the new GDT
121 # Copy the Interrupt Descriptor Table to our space
124 sidt _Original_IDTR # save original IDT
125 movzwl _Original_IDTR_limit,%ecx # size of IDT in bytes; limit
126 # is 256 entries * 8 bytes per
129 # make ds:esi point to the original IDT
130 movl _Original_IDTR_base,%esi
136 # make es:edi point to the new (our copy) IDT
137 movl $_Interrupt_descriptor_table,%edi
140 movsb # copy the IDT (ds:esi -> es:edi)
143 # Build and load new contents of IDTR
144 movw _Original_IDTR_limit,%ecx # set new limit
145 movw %cx,_New_IDTR_limit
147 push $_Interrupt_descriptor_table
149 call _Logical_to_physical
151 movl %eax,_New_IDTR_base # set new base
153 cmpb $0,_Do_Load_IDT # Should the new IDT be loaded?
154 je no_idt_load # NO, then branch
155 lidt _New_IDTR # load the new IDT
159 # Initialize the i387.
161 # Using the NO WAIT form of the instruction insures that if
162 # it is not present the board will not lock up or get an
166 fninit # MUST USE NO-WAIT FORM
168 call __Board_Initialize # initialize the board
170 pushl $0 # envp = NULL
171 pushl $0 # argv = NULL
172 pushl $0 # argc = NULL
173 call ___libc_init # initialize the library and
177 pushl $0 # argc = NULL
178 call __exit # call the Board specific exit
188 .global _return_to_monitor
191 cmpb $0,_Do_Load_IDT # Was the new IDT loaded?
192 je no_idt_restore # NO, then branch
193 lidt _Original_IDTR # restore the new IDT
196 cmpb $0,_Do_Load_GDT # Was the new GDT loaded?
197 je no_gdt_restore # NO, then branch
198 lgdt _Original_GDTR # restore the new GDT
200 jmp _return_to_monitor
203 # void *Logical_to_physical(
204 # rtems_unsigned16 segment,
208 # Returns thirty-two bit physical address for segment:address.
211 .global _Logical_to_physical
216 _Logical_to_physical:
218 xorl %eax,%eax # clear eax
219 movzwl SEGMENT_ARG(%esp),%ecx # ecx = segment value
220 movl $_Global_descriptor_table,%edx # edx = address of our GDT
221 addl %ecx,%edx # edx = address of desired entry
222 movb 7(%edx),%ah # ah = base 31:24
223 movb 4(%edx),%al # al = base 23:16
224 shll $16,%eax # move ax into correct bits
225 movw 2(%edx),%ax # ax = base 0:15
226 movl ADDRESS_ARG(%esp),%ecx # ecx = address to convert
227 addl %eax,%ecx # ecx = physical address equivalent
228 movl %ecx,%eax # eax = ecx
232 # void *Physical_to_logical(
233 # rtems_unsigned16 segment,
237 # Returns thirty-two bit physical address for segment:address.
240 .global _Physical_to_logical
243 #.set ADDRESS_ARG, 8 -- use sets from above
245 _Physical_to_logical:
247 xorl %eax,%eax # clear eax
248 movzwl SEGMENT_ARG(%esp),%ecx # ecx = segment value
249 movl $_Global_descriptor_table,%edx # edx = address of our GDT
250 addl %ecx,%edx # edx = address of desired entry
251 movb 7(%edx),%ah # ah = base 31:24
252 movb 4(%edx),%al # al = base 23:16
253 shll $16,%eax # move ax into correct bits
254 movw 2(%edx),%ax # ax = base 0:15
255 movl ADDRESS_ARG(%esp),%ecx # ecx = address to convert
256 subl %eax,%ecx # ecx = logical address equivalent
257 movl %ecx,%eax # eax = ecx
262 * Data Declarations. Start with a macro which helps declare space.
267 #define DECLARE_SPACE(_name,_space,_align) \
270 _name##: .space _space
272 #define DECLARE_LABEL(_name) \
276 #define DECLARE_PTR(_name) DECLARE_SPACE(_name,4,2)
277 #define DECLARE_U32(_name) DECLARE_SPACE(_name,4,2)
278 #define DECLARE_U16(_name) DECLARE_SPACE(_name,2,1)
281 * Require environment stuff
284 DECLARE_LABEL(_environ)
287 DECLARE_LABEL(_errno)
291 * Miscellaneous Variables used to restore the CPU state.
293 * Start with a macro to declare the space for the contents of
294 * a Descriptor Table register.
297 #define DECLARE_DTR_SPACE(_name) \
301 _name##_limit: .space 2 ; \
302 _name##_base: .space 4
304 DECLARE_SPACE(_Interrupt_descriptor_table,256*8,4)
305 DECLARE_SPACE(_Global_descriptor_table,8192*8,4)
307 DECLARE_DTR_SPACE(_Original_IDTR)
308 DECLARE_DTR_SPACE(_New_IDTR)
309 DECLARE_DTR_SPACE(_Original_GDTR)
310 DECLARE_DTR_SPACE(_New_GDTR)
312 DECLARE_SPACE(_Physical_base_of_ds,4,4)
313 DECLARE_SPACE(_Physical_base_of_cs,4,4)
316 * Stack Size and Space
319 .set stack_size, 0x20000
321 DECLARE_SPACE(stack_memory,stack_size,4)
322 DECLARE_LABEL(stack_end)