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)