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 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.)
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
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.
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
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
52 .global start # GNU default entry point
53 .global _establish_stack
56 .global _load_segments
61 cli # DISABLE INTERRUPTS!!!
63 # Load the segment registers
65 # NOTE: Upon return, gs will contain the segment descriptor for
66 # a segment which maps directly to all of physical memory.
68 jmp _load_segments # load board dependent segments
76 movl $stack_end,%esp # set stack pointer
77 movl $stack_end,%ebp # set base pointer
80 # Zero out the BSS segment
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
93 # Set the C heap information for malloc
95 movl $heap_size,___C_heap_size # set ___C_heap_size
96 movl $heap_memory,___C_heap_start # set ___C_heap_start
99 # Copy the Global Descriptor Table to our space
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
106 # make ds:esi point to the original GDT
108 movl _Original_GDTR_base,%esi
113 # make es:edi point to the new (our copy) GDT
114 movl $_Global_descriptor_table,%edi
117 movsb # copy the GDT (ds:esi -> es:edi)
121 # Build and load new contents of GDTR
122 movw _Original_GDTR_limit,%ecx # set new limit
123 movw %cx,_New_GDTR_limit
125 push $_Global_descriptor_table
127 call _Logical_to_physical
129 movl %eax,_New_GDTR_base # set new base
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
137 # Copy the Interrupt Descriptor Table to our space
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
145 # make ds:esi point to the original IDT
146 movl _Original_IDTR_base,%esi
152 # make es:edi point to the new (our copy) IDT
153 movl $_Interrupt_descriptor_table,%edi
156 movsb # copy the IDT (ds:esi -> es:edi)
159 # Build and load new contents of IDTR
160 movw _Original_IDTR_limit,%ecx # set new limit
161 movw %cx,_New_IDTR_limit
163 push $_Interrupt_descriptor_table
165 call _Logical_to_physical
167 movl %eax,_New_IDTR_base # set new base
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
175 # Initialize the i387.
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
182 fninit # MUST USE NO-WAIT FORM
184 call __Board_Initialize # initialize the board
186 pushl $0 # envp = NULL
187 pushl $0 # argv = NULL
188 pushl $0 # argc = NULL
189 call ___libc_init # initialize the library and
193 pushl $0 # argc = NULL
194 call __exit # call the Board specific exit
204 .global _return_to_monitor
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
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
216 jmp _return_to_monitor
219 # void *Logical_to_physical(
220 # rtems_unsigned16 segment,
224 # Returns thirty-two bit physical address for segment:address.
227 .global _Logical_to_physical
232 _Logical_to_physical:
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
248 # void *Physical_to_logical(
249 # rtems_unsigned16 segment,
253 # Returns thirty-two bit physical address for segment:address.
256 .global _Physical_to_logical
259 #.set ADDRESS_ARG, 8 -- use sets from above
261 _Physical_to_logical:
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
278 * Data Declarations. Start with a macro which helps declare space.
283 #define DECLARE_SPACE(_name,_space,_align) \
286 _name##: .space _space
288 #define DECLARE_LABEL(_name) \
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)
297 * Require environment stuff
300 DECLARE_LABEL(_environ)
303 DECLARE_LABEL(_errno)
307 * Miscellaneous Variables used to restore the CPU state.
309 * Start with a macro to declare the space for the contents of
310 * a Descriptor Table register.
313 #define DECLARE_DTR_SPACE(_name) \
317 _name##_limit: .space 2 ; \
318 _name##_base: .space 4
320 DECLARE_SPACE(_Interrupt_descriptor_table,256*8,4)
321 DECLARE_SPACE(_Global_descriptor_table,8192*8,4)
323 DECLARE_DTR_SPACE(_Original_IDTR)
324 DECLARE_DTR_SPACE(_New_IDTR)
325 DECLARE_DTR_SPACE(_Original_GDTR)
326 DECLARE_DTR_SPACE(_New_GDTR)
328 DECLARE_SPACE(_Physical_base_of_ds,4,4)
329 DECLARE_SPACE(_Physical_base_of_cs,4,4)
332 * Stack Size and Space
335 .set stack_size, 0x20000
337 DECLARE_SPACE(stack_memory,stack_size,4)
338 DECLARE_LABEL(stack_end)