aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/standalone/i386
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1995-02-18 01:27:10 +0000
committerRoland McGrath <roland@gnu.org>1995-02-18 01:27:10 +0000
commit28f540f45bbacd939bfd07f213bcad2bf730b1bf (patch)
tree15f07c4c43d635959c6afee96bde71fb1b3614ee /sysdeps/standalone/i386
downloadglibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.tar
glibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.tar.gz
glibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.tar.bz2
glibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.zip
initial import
Diffstat (limited to 'sysdeps/standalone/i386')
-rw-r--r--sysdeps/standalone/i386/Dist1
-rw-r--r--sysdeps/standalone/i386/force_cpu386/Dist1
-rw-r--r--sysdeps/standalone/i386/force_cpu386/Makefile24
-rw-r--r--sysdeps/standalone/i386/force_cpu386/_exit.c47
-rw-r--r--sysdeps/standalone/i386/force_cpu386/brdinit.c44
-rw-r--r--sysdeps/standalone/i386/force_cpu386/console.c163
-rw-r--r--sysdeps/standalone/i386/force_cpu386/strtsupp.S89
-rw-r--r--sysdeps/standalone/i386/force_cpu386/target.ld59
-rw-r--r--sysdeps/standalone/i386/i386.h327
-rw-r--r--sysdeps/standalone/i386/start.S323
10 files changed, 1078 insertions, 0 deletions
diff --git a/sysdeps/standalone/i386/Dist b/sysdeps/standalone/i386/Dist
new file mode 100644
index 0000000000..98d13be9af
--- /dev/null
+++ b/sysdeps/standalone/i386/Dist
@@ -0,0 +1 @@
+i386.h
diff --git a/sysdeps/standalone/i386/force_cpu386/Dist b/sysdeps/standalone/i386/force_cpu386/Dist
new file mode 100644
index 0000000000..8b7b09e10a
--- /dev/null
+++ b/sysdeps/standalone/i386/force_cpu386/Dist
@@ -0,0 +1 @@
+target.ld
diff --git a/sysdeps/standalone/i386/force_cpu386/Makefile b/sysdeps/standalone/i386/force_cpu386/Makefile
new file mode 100644
index 0000000000..8483724ee3
--- /dev/null
+++ b/sysdeps/standalone/i386/force_cpu386/Makefile
@@ -0,0 +1,24 @@
+# Copyright (C) 1994 Free Software Foundation, Inc.
+# Contributed by Joel Sherrill (jsherril@redstone-emh2.army.mil),
+# On-Line Applications Research Corporation.
+
+# 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.
+
+ifeq (bare,$(subdir))
+install-others += $(libdir)/force_cpu386.ld
+$(libdir)/force_cpu386.ld: $(sysdep_dir)/standalone/i386/target.ld
+ $(do-install)
+endif
diff --git a/sysdeps/standalone/i386/force_cpu386/_exit.c b/sysdeps/standalone/i386/force_cpu386/_exit.c
new file mode 100644
index 0000000000..011bb8bda9
--- /dev/null
+++ b/sysdeps/standalone/i386/force_cpu386/_exit.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 1991 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. */
+
+#include <ansidecl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+/* This returns control to FORCEbug. */
+
+void DEFUN_VOID(Bsp_cleanup);
+
+/* The function `_exit' should take a status argument and simply
+ terminate program execution, using the low-order 8 bits of the
+ given integer as status. */
+
+__NORETURN void
+DEFUN(_exit, (status), int status)
+{
+ /* status is ignored */
+ Bsp_cleanup();
+}
+
+#ifdef HAVE_GNU_LD
+
+#include <gnu-stabs.h>
+
+stub_warning(_exit);
+
+#endif /* GNU stabs. */
diff --git a/sysdeps/standalone/i386/force_cpu386/brdinit.c b/sysdeps/standalone/i386/force_cpu386/brdinit.c
new file mode 100644
index 0000000000..0d27218121
--- /dev/null
+++ b/sysdeps/standalone/i386/force_cpu386/brdinit.c
@@ -0,0 +1,44 @@
+/* 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. */
+
+#include <ansidecl.h>
+#include <standalone.h>
+#include "i386.h"
+
+/* _Board_Initialize()
+
+This routine initializes the FORCE CPU386 board. */
+
+void DEFUN_VOID(_Console_Initialize);
+
+void
+DEFUN_VOID(_Board_Initialize)
+{
+ /*
+ * FORCE documentation incorrectly states that the bus request
+ * level is initialized to 3. It is actually initialized by
+ * FORCEbug to 0.
+ */
+
+ outport_byte( 0x00, 0x3f ); /* resets VMEbus request level */
+
+ _Console_Initialize();
+}
diff --git a/sysdeps/standalone/i386/force_cpu386/console.c b/sysdeps/standalone/i386/force_cpu386/console.c
new file mode 100644
index 0000000000..5d56f768ea
--- /dev/null
+++ b/sysdeps/standalone/i386/force_cpu386/console.c
@@ -0,0 +1,163 @@
+/* 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. */
+
+#include <ansidecl.h>
+#include <standalone.h>
+#include "i386.h"
+
+/* Console IO routines for a FORCE CPU386 board. */
+
+/* Force CPU/386 specific IO addressing
+ *
+ * The following determines whether Port B or the Console should
+ * be used for console I/O. Setting ONE (and only ONE) of these to 1
+ * enables I/O on that port.
+ *
+ * PORT A - DUSCC MC68562 Channel A (*** not supported here ***)
+ * PORT B - DUSCC MC68562 Channel B
+ * PORT C - MFP MC68901 Channel (*** FORCEbug console ***)
+ */
+
+#define PORTB 1 /* use port b as console */
+#define PORTC 0 /* use console port as console */
+
+#if ( PORTB == 1 )
+#define TX_STATUS 0x1b6 /* DUSCC General Status Register */
+#define RX_STATUS 0x1b6 /* DUSCC General Status Register */
+#define TX_BUFFER 0x1e0 /* DUSCC Transmitter Channel B */
+#define RX_BUFFER 0x1e8 /* DUSCC Receiver Channel B */
+#define Is_tx_ready( _status ) ( (_status) & 0x20 )
+#define Is_rx_ready( _status ) ( (_status) & 0x10 )
+#endif
+
+#if ( PORTC == 1 )
+#define TX_STATUS 0x12c /* MFP Transmit Status Register */
+#define RX_STATUS 0x12a /* MFP Receive Status Register */
+#define TX_BUFFER 0x12e /* MFP Transmitter Channel */
+#define RX_BUFFER 0x12e /* MFP Receiver Channel */
+#define Is_tx_ready( _status ) ( (_status) & 0x80 )
+#define Is_rx_ready( _status ) ( (_status) & 0x80 )
+#endif
+
+/* _Console_Initialize
+
+On the Force board the console require some initialization. */
+
+void
+DEFUN_VOID(_Console_Initialize)
+{
+ register unsigned8 ignored;
+
+ /* FORCE technical support mentioned that it may be necessary to
+ read the DUSCC RX_BUFFER port four times to remove all junk.
+ This code is a little more paranoid. */
+
+ inport_byte( RX_BUFFER, ignored );
+ inport_byte( RX_BUFFER, ignored );
+ inport_byte( RX_BUFFER, ignored );
+ inport_byte( RX_BUFFER, ignored );
+ inport_byte( RX_BUFFER, ignored );
+}
+
+/* Miscellaneous support for console IO */
+
+static inline int _Force386_is_rx_ready()
+{
+ register unsigned8 status;
+
+ inport_byte( RX_STATUS, status );
+
+ if ( Is_rx_ready( status ) ) return 1;
+ else return 0;
+}
+
+static inline int _Force386_is_tx_ready()
+{
+ register unsigned8 status;
+
+ inport_byte( TX_STATUS, status );
+
+ if ( Is_tx_ready( status ) ) return 1;
+ else return 0;
+}
+
+
+static inline int _Force386_read_data()
+{
+ register unsigned8 ch;
+
+#if ( PORTB == 1 )
+ /* Force example code resets the Channel B Receiver here.
+ * It appears to cause XON's to be lost.
+ */
+
+ /* outport_byte( RX_STATUS, 0x10 ); */
+#endif
+
+ inport_byte( RX_BUFFER, ch );
+
+ return ch;
+}
+
+/* _Console_Putc
+
+This routine transmits a character. It supports XON/XOFF flow control. */
+
+#define XON 0x11 /* control-Q */
+#define XOFF 0x13 /* control-S */
+
+int
+DEFUN( _Console_Putc, (ch), char ch )
+{
+ register unsigned8 inch;
+
+ while ( !_Force386_is_tx_ready() );
+
+ while ( _Force386_is_rx_ready() == 1 ) { /* must be an XOFF */
+ inch = _Force386_read_data();
+ if ( inch == XOFF )
+ do {
+ while ( _Force386_is_rx_ready() == 0 );
+ inch = _Force386_read_data();
+ } while ( inch != XON );
+ }
+
+ outport_byte( TX_BUFFER, ch );
+ return( 0 );
+}
+
+/* _Console_Getc
+
+This routine reads a character from the UART and returns it. */
+
+int
+DEFUN( _Console_Getc, (poll), int poll )
+{
+ if ( poll ) {
+ if ( !_Force386_is_rx_ready() )
+ return -1;
+ else
+ return _Force386_read_data();
+ } else {
+ while ( !_Force386_is_rx_ready() );
+ return _Force386_read_data();
+ }
+}
diff --git a/sysdeps/standalone/i386/force_cpu386/strtsupp.S b/sysdeps/standalone/i386/force_cpu386/strtsupp.S
new file mode 100644
index 0000000000..6b78a8c343
--- /dev/null
+++ b/sysdeps/standalone/i386/force_cpu386/strtsupp.S
@@ -0,0 +1,89 @@
+/* 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. */
+
+/* This file assists the board independent startup code by
+ * loading the proper segment register values. The values
+ * loaded are dependent on the FORCEBUG.
+ *
+ * NOTE: No stack has been established when this routine
+ * is invoked. It returns by jumping back to the start code.
+ *
+ */
+
+/*
+ * FORCEBUG loads us into a virtual address space which
+ * really starts at PHYSICAL_ADDRESS_BASE.
+ *
+ */
+
+.set PHYSICAL_ADDRESS_BASE, 0x00002000
+
+/*
+ * At reset time, FORCEBUG normally has the segment selectors preloaded.
+ * If a human resets the instruction pointer, this will not have occurred.
+ * However, no guarantee can be made of the other registers if cs:ip was
+ * modified to restart the program. Because of this, the BSP reloads all
+ * segment registers (except cs) with the values they have following
+ * a reset.
+ */
+
+
+.set RESET_SS, 0x40 # initial value of stack segment register
+.set RESET_DS, 0x40 # initial value of data segment register
+.set RESET_ES, 0x40 # initial value of extra segment register
+.set RESET_FS, 0x40 # initial value of "f" segment register
+.set RESET_GS, 0x30 # initial value of "g" segment register
+
+
+#define LOAD_SEGMENTS(_value,_segreg) \
+ movw $_value##,%ax ; \
+ movw %ax,##_segreg
+
+
+ .global _load_segments
+
+ .global _establish_stack
+
+_load_segments:
+
+ LOAD_SEGMENTS( RESET_SS, %ss )
+ LOAD_SEGMENTS( RESET_DS, %ds )
+ LOAD_SEGMENTS( RESET_ES, %es )
+ LOAD_SEGMENTS( RESET_FS, %fs )
+ LOAD_SEGMENTS( RESET_GS, %gs )
+
+ jmp _establish_stack # return to the bsp entry code
+
+ .global _return_to_monitor
+_return_to_monitor:
+
+ movb $0,%al
+ int $0x20 # restart FORCEbug
+ jmp start # FORCEbug does not reset PC
+
+ .data
+
+ .global _Do_Load_IDT
+_Do_Load_IDT: .byte 1
+
+ .global _Do_Load_GDT
+_Do_Load_GDT: .byte 0
+
diff --git a/sysdeps/standalone/i386/force_cpu386/target.ld b/sysdeps/standalone/i386/force_cpu386/target.ld
new file mode 100644
index 0000000000..056da10d55
--- /dev/null
+++ b/sysdeps/standalone/i386/force_cpu386/target.ld
@@ -0,0 +1,59 @@
+/* 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. */
+
+/* This file contains directives for the GNU linker which are specific
+to the FORCE CPU386 board. */
+
+MEMORY
+ {
+ ram : org = 0x0, l = 1M
+ }
+
+/* This value is also when the space is allocated. If you change
+this one, change the other one!!! */
+
+heap_size = 0x20000;
+
+SECTIONS
+{
+ .text 0x0 :
+ {
+ _text_start = ABSOLUTE(.) ;
+ *(.text)
+ _etext = ALIGN( 0x10 ) ;
+ }
+ .data ADDR( .text ) + SIZEOF( .text ):
+ {
+ _data_start = . ;
+ *(.data)
+ _edata = ALIGN( 0x10 ) ;
+ }
+ .bss ADDR( .data ) + SIZEOF( .data ):
+ {
+ _bss_start = . ;
+ *(.bss)
+ *(COMMON)
+ heap_memory = .;
+ . += 0x20000;
+ _end = . ;
+ __end = . ;
+ }
+}
diff --git a/sysdeps/standalone/i386/i386.h b/sysdeps/standalone/i386/i386.h
new file mode 100644
index 0000000000..8302773709
--- /dev/null
+++ b/sysdeps/standalone/i386/i386.h
@@ -0,0 +1,327 @@
+/* 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. */
+
+/* i386.h
+ *
+ * This file contains macros which are used to access i80386
+ * registers which are not addressable by C. This file contains
+ * functions which are useful to those developing target
+ * specific support routines.
+ */
+
+#ifndef i386_h__
+#define i386_h__
+
+typedef unsigned char unsigned8;
+typedef unsigned short unsigned16;
+typedef unsigned int unsigned32;
+
+#define disable_intr( isrlevel ) \
+ { (isrlevel) = 0; \
+ asm volatile ( "pushf ; \
+ pop %0 ; \
+ cli " \
+ : "=r" ((isrlevel)) : "0" ((isrlevel)) ); \
+ }
+
+
+#define enable_intr( isrlevel ) \
+ { asm volatile ( "push %0 ; \
+ popf " \
+ : "=r" ((isrlevel)) : "0" ((isrlevel)) ); \
+ }
+
+#define delay( _microseconds ) \
+ { \
+ unsigned32 _counter; \
+ \
+ _counter = (_microseconds); \
+ \
+ asm volatile ( "0: nop;" \
+ " mov %0,%0 ;" \
+ " loop 0" : "=c" (_counter) \
+ : "0" (_counter) \
+ ); \
+ \
+ }
+
+/* segment access functions */
+
+static inline unsigned16 get_cs()
+{
+ register unsigned16 segment = 0;
+
+ asm volatile ( "movw %%cs,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline unsigned16 get_ds()
+{
+ register unsigned16 segment = 0;
+
+ asm volatile ( "movw %%ds,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline unsigned16 get_es()
+{
+ register unsigned16 segment = 0;
+
+ asm volatile ( "movw %%es,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline unsigned16 get_ss()
+{
+ register unsigned16 segment = 0;
+
+ asm volatile ( "movw %%ss,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline unsigned16 get_fs()
+{
+ register unsigned16 segment = 0;
+
+ asm volatile ( "movw %%fs,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline unsigned16 get_gs()
+{
+ register unsigned16 segment = 0;
+
+ asm volatile ( "movw %%gs,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+/* i80x86 I/O instructions */
+
+#define outport_byte( _port, _value ) \
+ { register unsigned16 __port = _port; \
+ register unsigned8 __value = _value; \
+ \
+ asm volatile ( "outb %0,%1" : "=a" (__value), "=d" (__port) \
+ : "0" (__value), "1" (__port) \
+ ); \
+ }
+
+#define outport_word( _port, _value ) \
+ { register unsigned16 __port = _port; \
+ register unsigned16 __value = _value; \
+ \
+ asm volatile ( "outw %0,%1" : "=a" (__value), "=d" (__port) \
+ : "0" (__value), "1" (__port) \
+ ); \
+ }
+
+#define outport_long( _port, _value ) \
+ { register unsigned16 __port = _port; \
+ register unsigned32 __value = _value; \
+ \
+ asm volatile ( "outl %0,%1" : "=a" (__value), "=d" (__port) \
+ : "0" (__value), "1" (__port) \
+ ); \
+ }
+
+#define inport_byte( _port, _value ) \
+ { register unsigned16 __port = _port; \
+ register unsigned8 __value = 0; \
+ \
+ asm volatile ( "inb %1,%0" : "=a" (__value), "=d" (__port) \
+ : "0" (__value), "1" (__port) \
+ ); \
+ _value = __value; \
+ }
+
+#define inport_word( _port, _value ) \
+ { register unsigned16 __port = _port; \
+ register unsigned16 __value = 0; \
+ \
+ asm volatile ( "inw %1,%0" : "=a" (__value), "=d" (__port) \
+ : "0" (__value), "1" (__port) \
+ ); \
+ _value = __value; \
+ }
+
+#define inport_long( _port, _value ) \
+ { register unsigned16 __port = _port; \
+ register unsigned32 __value = 0; \
+ \
+ asm volatile ( "inl %1,%0" : "=a" (__value), "=d" (__port) \
+ : "0" (__value), "1" (__port) \
+ ); \
+ _value = __value; \
+ }
+
+/* structures */
+
+/* See Chapter 5 - Memory Management in i386 manual */
+
+struct GDT_slot {
+ unsigned16 limit_0_15;
+ unsigned16 base_0_15;
+ unsigned8 base_16_23;
+ unsigned8 type_dt_dpl_p;
+ unsigned8 limit_16_19_granularity;
+ unsigned8 base_24_31;
+};
+
+/* See Chapter 9 - Exceptions and Interrupts in i386 manual
+ *
+ * NOTE: This is the IDT entry for interrupt gates ONLY.
+ */
+
+struct IDT_slot {
+ unsigned16 offset_0_15;
+ unsigned16 segment_selector;
+ unsigned8 reserved;
+ unsigned8 p_dpl;
+ unsigned16 offset_16_31;
+};
+
+struct DTR_load_save_format {
+ unsigned16 limit;
+ unsigned32 physical_address;
+};
+
+/* variables */
+
+extern struct IDT_slot Interrupt_descriptor_table[ 256 ];
+extern struct GDT_slot Global_descriptor_table[ 8192 ];
+
+/* functions */
+
+#ifdef CPU_INITIALIZE
+#define EXTERN
+#else
+#undef EXTERN
+#define EXTERN extern
+#endif
+
+void *Logical_to_physical(
+ unsigned16 segment,
+ void *address
+);
+
+void *Physical_to_logical(
+ unsigned16 segment,
+ void *address
+);
+
+/* complicated static inline functions */
+
+#define get_GDTR( _gdtr_address ) \
+ { \
+ void *_gdtr = (_gdtr_address); \
+ \
+ asm volatile( "sgdt (%0)" : "=r" (_gdtr) : "0" (_gdtr) ); \
+ }
+
+#define get_GDT_slot( _gdtr_base, _segment, _slot_address ) \
+ { \
+ register unsigned32 _gdt_slot = (_gdtr_base) + (_segment); \
+ register volatile void *_slot = (_slot_address); \
+ register unsigned32 _temporary = 0; \
+ \
+ asm volatile( "movl %%gs:(%0),%1 ; \
+ movl %1,(%2) ; \
+ movl %%gs:4(%0),%1 ; \
+ movl %1,4(%2)" \
+ : "=r" (_gdt_slot), "=r" (_temporary), "=r" (_slot) \
+ : "0" (_gdt_slot), "1" (_temporary), "2" (_slot) \
+ ); \
+ }
+
+#define set_GDT_slot( _gdtr_base, _segment, _slot_address ) \
+ { \
+ register unsigned32 _gdt_slot = (_gdtr_base) + (_segment); \
+ register volatile void *_slot = (_slot_address); \
+ register unsigned32 _temporary = 0; \
+ \
+ asm volatile( "movl (%2),%1 ; \
+ movl %1,%%gs:(%0) ; \
+ movl 4(%2),%1 ; \
+ movl %1,%%gs:4(%0) \
+ " \
+ : "=r" (_gdt_slot), "=r" (_temporary), "=r" (_slot) \
+ : "0" (_gdt_slot), "1" (_temporary), "2" (_slot) \
+ ); \
+ }
+
+static inline void set_segment(
+ unsigned16 segment,
+ unsigned32 base,
+ unsigned32 limit
+)
+{
+ struct DTR_load_save_format gdtr;
+ volatile struct GDT_slot Gdt_slot;
+ volatile struct GDT_slot *gdt_slot = &Gdt_slot;
+ unsigned16 tmp_segment = 0;
+ unsigned32 limit_adjusted;
+
+
+ /* load physical address of the GDT */
+
+ get_GDTR( &gdtr );
+
+ gdt_slot->type_dt_dpl_p = 0x92; /* present, dpl=0, */
+ /* application=1, */
+ /* type=data read/write */
+ gdt_slot->limit_16_19_granularity = 0x40; /* 32 bit segment */
+
+ limit_adjusted = limit;
+ if ( limit > 4095 ) {
+ gdt_slot->limit_16_19_granularity |= 0x80; /* set granularity bit */
+ limit_adjusted /= 4096;
+ }
+
+ gdt_slot->limit_16_19_granularity |= (limit_adjusted >> 16) & 0xff;
+ gdt_slot->limit_0_15 = limit_adjusted & 0xffff;
+
+ gdt_slot->base_0_15 = base & 0xffff;
+ gdt_slot->base_16_23 = (base >> 16) & 0xff;
+ gdt_slot->base_24_31 = (base >> 24);
+
+ set_GDT_slot( gdtr.physical_address, segment, gdt_slot );
+
+ /* Now, reload all segment registers so the limit takes effect. */
+
+ asm volatile( "movw %%ds,%0 ; movw %0,%%ds
+ movw %%es,%0 ; movw %0,%%es
+ movw %%fs,%0 ; movw %0,%%fs
+ movw %%gs,%0 ; movw %0,%%gs
+ movw %%ss,%0 ; movw %0,%%ss"
+ : "=r" (tmp_segment)
+ : "0" (tmp_segment)
+ );
+
+}
+
+#endif
+/* end of include file */
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)
+