about summary refs log tree commit diff
path: root/sysdeps/standalone/i386/start.S
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/standalone/i386/start.S')
-rw-r--r--sysdeps/standalone/i386/start.S323
1 files changed, 323 insertions, 0 deletions
diff --git a/sysdeps/standalone/i386/start.S b/sysdeps/standalone/i386/start.S
new file mode 100644
index 0000000000..8331a331c1
--- /dev/null
+++ b/sysdeps/standalone/i386/start.S
@@ -0,0 +1,323 @@
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+   Contributed by Joel Sherrill (jsherril@redstone-emh2.army.mil),
+     On-Line Applications Research Corporation.
+ 
+This file is part of the GNU C Library.
+ 
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+ 
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+ 
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/*  entry.s
+ *
+ *  This file contains the entry point for the application.
+ *  The name of this entry point is compiler dependent.
+ *  It jumps to the BSP which is responsible for performing
+ *  all initialization.
+ *
+ */
+
+        .data
+        .global  _Do_Load_IDT
+        .global  _Do_Load_GDT
+
+        .text
+	      .global  start                  # GNU default entry point
+        .global  _establish_stack
+
+        .global   _bsp_start
+        .global   _load_segments
+        .global   __exit
+
+start:
+        nop
+        cli                             # DISABLE INTERRUPTS!!!
+#
+#  Load the segment registers
+#
+#  NOTE: Upon return, gs will contain the segment descriptor for
+#        a segment which maps directly to all of physical memory.
+#
+        jmp     _load_segments          # load board dependent segments
+
+#
+#  Set up the stack
+#
+
+_establish_stack:
+
+        movl    $stack_end,%esp         # set stack pointer
+        movl    $stack_end,%ebp         # set base pointer
+
+#
+#  Zero out the BSS segment
+#
+zero_bss:
+        cld                             # make direction flag count up
+        movl    $_end,%ecx              # find end of .bss
+        movl    $_bss_start,%edi        # edi = beginning of .bss
+        subl    %edi,%ecx               # ecx = size of .bss in bytes
+        shrl    $2,%ecx                 # size of .bss in longs
+        xorl    %eax,%eax               # value to clear out memory
+        repne                           # while ecx != 0
+        stosl                           #   clear a long in the bss
+
+#
+#  Set the C heap information for malloc
+#
+        movl    $heap_size,___C_heap_size    # set ___C_heap_size
+        movl    $heap_memory,___C_heap_start # set ___C_heap_start
+
+#
+#  Copy the Global Descriptor Table to our space
+#
+
+        sgdt    _Original_GDTR          # save original GDT
+        movzwl  _Original_GDTR_limit,%ecx # size of GDT in bytes; limit 
+                                          #   is 8192 entries * 8 bytes per
+
+        # make ds:esi point to the original GDT
+
+        movl    _Original_GDTR_base,%esi
+        push    %ds                     # save ds
+        movw    %gs,%ax
+        movw    %ax,%ds 
+
+        # make es:edi point to the new (our copy) GDT
+        movl    $_Global_descriptor_table,%edi
+
+        rep
+        movsb                            # copy the GDT (ds:esi -> es:edi)
+
+        pop     %ds                      # restore ds
+      
+        # Build and load new contents of GDTR
+        movw    _Original_GDTR_limit,%ecx # set new limit
+        movw    %cx,_New_GDTR_limit
+
+        push    $_Global_descriptor_table
+        push    %es
+        call    _Logical_to_physical
+        addl    $6,%esp
+        movl    %eax,_New_GDTR_base      # set new base
+
+        cmpb    $0,_Do_Load_GDT          # Should the new GDT be loaded?
+        je      no_gdt_load              # NO, then branch
+        lgdt    _New_GDTR                # load the new GDT
+no_gdt_load:
+
+#
+#  Copy the Interrupt Descriptor Table to our space
+#
+
+        sidt    _Original_IDTR          # save original IDT
+        movzwl  _Original_IDTR_limit,%ecx # size of IDT in bytes; limit
+                                          #   is 256 entries * 8 bytes per
+ 
+
+        # make ds:esi point to the original IDT
+        movl    _Original_IDTR_base,%esi
+
+        push    %ds                     # save ds
+        movw    %gs,%ax
+        movw    %ax,%ds 
+
+        # make es:edi point to the new (our copy) IDT
+        movl    $_Interrupt_descriptor_table,%edi
+
+        rep
+        movsb                            # copy the IDT (ds:esi -> es:edi)
+        pop     %ds                      # restore ds
+
+        # Build and load new contents of IDTR
+        movw    _Original_IDTR_limit,%ecx # set new limit
+        movw    %cx,_New_IDTR_limit
+
+        push    $_Interrupt_descriptor_table
+        push    %es
+        call    _Logical_to_physical
+        addl    $6,%esp
+        movl    %eax,_New_IDTR_base      # set new base
+
+        cmpb    $0,_Do_Load_IDT          # Should the new IDT be loaded?
+        je      no_idt_load              # NO, then branch
+        lidt    _New_IDTR                # load the new IDT
+no_idt_load:
+
+#
+#  Initialize the i387.
+#
+#  Using the NO WAIT form of the instruction insures that if
+#  it is not present the board will not lock up or get an
+#  exception.
+#
+
+        fninit                           # MUST USE NO-WAIT FORM
+
+        call    __Board_Initialize       # initialize the board
+
+        pushl   $0                       # envp = NULL 
+        pushl   $0                       # argv = NULL 
+        pushl   $0                       # argc = NULL 
+        call    ___libc_init             # initialize the library and
+                                         #   call main
+        addl    $12,%esp
+ 
+        pushl   $0                       # argc = NULL 
+        call    __exit                   # call the Board specific exit
+        addl     $4,%esp
+
+#
+#  Clean up
+#
+
+
+        .global  _Bsp_cleanup
+
+        .global   _return_to_monitor
+
+_Bsp_cleanup:
+        cmpb    $0,_Do_Load_IDT          # Was the new IDT loaded?
+        je      no_idt_restore           # NO, then branch
+        lidt    _Original_IDTR           # restore the new IDT
+no_idt_restore:
+
+        cmpb    $0,_Do_Load_GDT          # Was the new GDT loaded?
+        je      no_gdt_restore           # NO, then branch
+        lgdt    _Original_GDTR           # restore the new GDT
+no_gdt_restore:
+        jmp     _return_to_monitor
+
+#
+#  void *Logical_to_physical( 
+#     rtems_unsigned16  segment,
+#     void             *address
+#  );
+#
+#  Returns thirty-two bit physical address for segment:address.
+#
+
+        .global  _Logical_to_physical
+
+.set SEGMENT_ARG, 4
+.set ADDRESS_ARG, 8
+
+_Logical_to_physical:
+
+        xorl    %eax,%eax                # clear eax
+        movzwl  SEGMENT_ARG(%esp),%ecx   # ecx = segment value
+        movl    $_Global_descriptor_table,%edx # edx = address of our GDT
+        addl    %ecx,%edx                # edx = address of desired entry
+        movb    7(%edx),%ah              # ah = base 31:24
+        movb    4(%edx),%al              # al = base 23:16
+        shll    $16,%eax                 # move ax into correct bits
+        movw    2(%edx),%ax              # ax = base 0:15
+        movl    ADDRESS_ARG(%esp),%ecx   # ecx = address to convert
+        addl    %eax,%ecx                # ecx = physical address equivalent
+        movl    %ecx,%eax                # eax = ecx
+        ret
+       
+#
+#  void *Physical_to_logical( 
+#     rtems_unsigned16  segment,
+#     void             *address
+#  );
+#
+#  Returns thirty-two bit physical address for segment:address.
+#
+
+        .global  _Physical_to_logical
+
+#.set SEGMENT_ARG, 4
+#.set ADDRESS_ARG, 8   -- use sets from above
+
+_Physical_to_logical:
+
+        xorl    %eax,%eax                # clear eax
+        movzwl  SEGMENT_ARG(%esp),%ecx   # ecx = segment value
+        movl    $_Global_descriptor_table,%edx # edx = address of our GDT
+        addl    %ecx,%edx                # edx = address of desired entry
+        movb    7(%edx),%ah              # ah = base 31:24
+        movb    4(%edx),%al              # al = base 23:16
+        shll    $16,%eax                 # move ax into correct bits
+        movw    2(%edx),%ax              # ax = base 0:15
+        movl    ADDRESS_ARG(%esp),%ecx   # ecx = address to convert
+        subl    %eax,%ecx                # ecx = logical address equivalent
+        movl    %ecx,%eax                # eax = ecx
+        ret
+       
+
+/*
+ *  Data Declarations.  Start with a macro which helps declare space.
+ */
+
+        .bss
+
+#define DECLARE_SPACE(_name,_space,_align) \
+          .globl   _name ; \
+          .align   _align ; \
+_name##:  .space _space
+
+#define DECLARE_LABEL(_name) \
+          .globl   _name ; \
+_name##:  
+
+#define DECLARE_PTR(_name) DECLARE_SPACE(_name,4,2)
+#define DECLARE_U32(_name) DECLARE_SPACE(_name,4,2)
+#define DECLARE_U16(_name) DECLARE_SPACE(_name,2,1)
+
+/*
+ *  Require environment stuff
+ */
+
+DECLARE_LABEL(_environ)
+DECLARE_PTR(environ)
+
+DECLARE_LABEL(_errno)
+DECLARE_U32(errno)
+
+/* 
+ *  Miscellaneous Variables used to restore the CPU state.
+ *
+ *  Start with a macro to declare the space for the contents of
+ *  a Descriptor Table register.
+ */
+
+#define DECLARE_DTR_SPACE(_name) \
+          .global   _name ; \
+          .align    4 ; \
+_name##:  ; \
+_name##_limit:  .space 2  ; \
+_name##_base:   .space 4
+
+DECLARE_SPACE(_Interrupt_descriptor_table,256*8,4)
+DECLARE_SPACE(_Global_descriptor_table,8192*8,4)
+
+DECLARE_DTR_SPACE(_Original_IDTR)
+DECLARE_DTR_SPACE(_New_IDTR)
+DECLARE_DTR_SPACE(_Original_GDTR)
+DECLARE_DTR_SPACE(_New_GDTR)
+
+DECLARE_SPACE(_Physical_base_of_ds,4,4)
+DECLARE_SPACE(_Physical_base_of_cs,4,4)
+
+/*
+ *  Stack Size and Space
+ */
+
+        .set stack_size, 0x20000
+
+DECLARE_SPACE(stack_memory,stack_size,4)
+DECLARE_LABEL(stack_end)
+