From 28f540f45bbacd939bfd07f213bcad2bf730b1bf Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sat, 18 Feb 1995 01:27:10 +0000 Subject: initial import --- sysdeps/standalone/i386/Dist | 1 + sysdeps/standalone/i386/force_cpu386/Dist | 1 + sysdeps/standalone/i386/force_cpu386/Makefile | 24 ++ sysdeps/standalone/i386/force_cpu386/_exit.c | 47 ++++ sysdeps/standalone/i386/force_cpu386/brdinit.c | 44 ++++ sysdeps/standalone/i386/force_cpu386/console.c | 163 ++++++++++++ sysdeps/standalone/i386/force_cpu386/strtsupp.S | 89 +++++++ sysdeps/standalone/i386/force_cpu386/target.ld | 59 +++++ sysdeps/standalone/i386/i386.h | 327 ++++++++++++++++++++++++ sysdeps/standalone/i386/start.S | 323 +++++++++++++++++++++++ 10 files changed, 1078 insertions(+) create mode 100644 sysdeps/standalone/i386/Dist create mode 100644 sysdeps/standalone/i386/force_cpu386/Dist create mode 100644 sysdeps/standalone/i386/force_cpu386/Makefile create mode 100644 sysdeps/standalone/i386/force_cpu386/_exit.c create mode 100644 sysdeps/standalone/i386/force_cpu386/brdinit.c create mode 100644 sysdeps/standalone/i386/force_cpu386/console.c create mode 100644 sysdeps/standalone/i386/force_cpu386/strtsupp.S create mode 100644 sysdeps/standalone/i386/force_cpu386/target.ld create mode 100644 sysdeps/standalone/i386/i386.h create mode 100644 sysdeps/standalone/i386/start.S (limited to 'sysdeps/standalone/i386') diff --git a/sysdeps/standalone/i386/Dist b/sysdeps/standalone/i386/Dist new file mode 100644 index 0000000..98d13be --- /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 0000000..8b7b09e --- /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 0000000..8483724 --- /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 0000000..011bb8b --- /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 +#include +#include + +/* 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 + +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 0000000..0d27218 --- /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 +#include +#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 0000000..5d56f76 --- /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 +#include +#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 0000000..6b78a8c --- /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 0000000..056da10 --- /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 0000000..8302773 --- /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 0000000..8331a33 --- /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) + -- cgit v1.1