summaryrefslogtreecommitdiffstats
path: root/c/src/exec/score/cpu/i386
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/exec/score/cpu/i386')
-rw-r--r--c/src/exec/score/cpu/i386/asm.h131
-rw-r--r--c/src/exec/score/cpu/i386/cpu.c121
-rw-r--r--c/src/exec/score/cpu/i386/cpu.h367
-rw-r--r--c/src/exec/score/cpu/i386/cpu_asm.s654
-rw-r--r--c/src/exec/score/cpu/i386/i386.h493
-rw-r--r--c/src/exec/score/cpu/i386/rtems.s31
6 files changed, 1797 insertions, 0 deletions
diff --git a/c/src/exec/score/cpu/i386/asm.h b/c/src/exec/score/cpu/i386/asm.h
new file mode 100644
index 0000000000..f123defcd9
--- /dev/null
+++ b/c/src/exec/score/cpu/i386/asm.h
@@ -0,0 +1,131 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __i386_ASM_h
+#define __i386_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#define ASM
+#include <i386.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+/*
+ * Looks like there is a bug in gcc 2.6.2 where this is not
+ * defined correctly when configured as i386-coff and
+ * i386-aout.
+ */
+
+#undef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__ %
+
+/*
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+*/
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+#define eax REG (eax)
+#define ebx REG (ebx)
+#define ecx REG (ecx)
+#define edx REG (edx)
+#define esi REG (esi)
+#define edi REG (edi)
+#define esp REG (esp)
+#define ebp REG (ebp)
+
+#define ax REG (ax)
+#define bx REG (bx)
+#define cx REG (cx)
+#define dx REG (dx)
+#define si REG (si)
+#define di REG (di)
+#define sp REG (sp)
+#define bp REG (bp)
+
+#define ah REG (ah)
+#define al REG (al)
+
+#define cs REG (cs)
+#define ds REG (ds)
+#define es REG (es)
+#define fs REG (fs)
+#define gs REG (gs)
+#define ss REG (ss)
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
+
+
diff --git a/c/src/exec/score/cpu/i386/cpu.c b/c/src/exec/score/cpu/i386/cpu.c
new file mode 100644
index 0000000000..05a836f7e3
--- /dev/null
+++ b/c/src/exec/score/cpu/i386/cpu.c
@@ -0,0 +1,121 @@
+/*
+ * Intel i386 Dependent Source
+ *
+ *
+ * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
+ * On-Line Applications Research Corporation (OAR).
+ * All rights assigned to U.S. Government, 1994.
+ *
+ * This material may be reproduced by or for the U.S. Government pursuant
+ * to the copyright license under the clause at DFARS 252.227-7013. This
+ * notice must appear in all copies of this file and its derivatives.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/fatal.h>
+#include <rtems/isr.h>
+#include <rtems/wkspace.h>
+
+/* _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * INPUT PARAMETERS:
+ * cpu_table - CPU table to initialize
+ * thread_dispatch - address of disptaching routine
+ */
+
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch) /* ignored on this CPU */
+)
+{
+ register unsigned16 fp_status asm ("ax");
+ register unsigned8 *fp_context;
+
+ if ( cpu_table == NULL )
+ rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED );
+
+ _CPU_Table = *cpu_table;
+
+ /*
+ * The following code saves a NULL i387 context which is given
+ * to each task at start and restart time. The following code
+ * is based upon that provided in the i386 Programmer's
+ * Manual and should work on any coprocessor greater than
+ * the i80287.
+ *
+ * NOTE: The NO RTEMS_WAIT form of the coprocessor instructions
+ * MUST be used in case there is not a coprocessor
+ * to wait for.
+ */
+
+ fp_status = 0xa5a5;
+ asm volatile( "fninit" );
+ asm volatile( "fnstsw %0" : "=a" (fp_status) : "0" (fp_status) );
+
+ if ( fp_status == 0 ) {
+
+ fp_context = _CPU_Null_fp_context;
+
+ asm volatile( "fsave (%0)" : "=r" (fp_context)
+ : "0" (fp_context)
+ );
+ }
+}
+
+/* _CPU_ISR_install_vector
+ *
+ * This kernel routine installs the RTEMS handler for the
+ * specified vector.
+ *
+ * Input parameters:
+ * vector - interrupt vector number
+ * old_handler - former ISR for this vector number
+ * new_handler - replacement ISR for this vector number
+ *
+ * Output parameters: NONE
+ *
+ */
+
+void _ISR_Handler_0(), _ISR_Handler_1();
+
+#define PER_ISR_ENTRY \
+ (((unsigned32) _ISR_Handler_1 - (unsigned32) _ISR_Handler_0))
+
+#define _Interrupt_Handler_entry( _vector ) \
+ (((unsigned32)_ISR_Handler_0) + ((_vector) * PER_ISR_ENTRY))
+
+void _CPU_ISR_install_vector(
+ unsigned32 vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ i386_IDT_slot idt;
+ unsigned32 unique_handler;
+
+ /* calculate the unique entry point for this vector */
+ unique_handler = _Interrupt_Handler_entry( vector );
+
+ /* build the IDT entry */
+ idt.offset_0_15 = ((unsigned32) unique_handler) & 0xffff;
+ idt.segment_selector = i386_get_cs();
+ idt.reserved = 0x00;
+ idt.p_dpl = 0x8e; /* present, ISR */
+ idt.offset_16_31 = ((unsigned32) unique_handler) >> 16;
+
+ /* install the IDT entry */
+ i386_Install_idt(
+ (unsigned32) &idt,
+ _CPU_Table.interrupt_table_segment,
+ (unsigned32) _CPU_Table.interrupt_table_offset + (8 * vector)
+ );
+
+ /* "portable" part */
+ *old_handler = _ISR_Vector_table[ vector ];
+ _ISR_Vector_table[ vector ] = new_handler;
+}
diff --git a/c/src/exec/score/cpu/i386/cpu.h b/c/src/exec/score/cpu/i386/cpu.h
new file mode 100644
index 0000000000..a66cb37abc
--- /dev/null
+++ b/c/src/exec/score/cpu/i386/cpu.h
@@ -0,0 +1,367 @@
+/* cpu.h
+ *
+ * This include file contains information pertaining to the Intel
+ * i386 processor.
+ *
+ * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
+ * On-Line Applications Research Corporation (OAR).
+ * All rights assigned to U.S. Government, 1994.
+ *
+ * This material may be reproduced by or for the U.S. Government pursuant
+ * to the copyright license under the clause at DFARS 252.227-7013. This
+ * notice must appear in all copies of this file and its derivatives.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_h
+#define __CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <i386.h>
+
+/* conditional compilation parameters */
+
+#define CPU_INLINE_ENABLE_DISPATCH TRUE
+#define CPU_UNROLL_ENQUEUE_PRIORITY FALSE
+
+/*
+ * i386 has an RTEMS allocated and managed interrupt stack.
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK TRUE
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE
+#define CPU_ALLOCATE_INTERRUPT_STACK TRUE
+
+/*
+ * Some family members have no FP, some have an FPU such as the i387
+ * for the i386, others have it built in (i486DX, Pentium).
+ */
+
+#if ( I386_HAS_FPU == 1 )
+#define CPU_HARDWARE_FP TRUE /* i387 for i386 */
+#else
+#define CPU_HARDWARE_FP FALSE
+#endif
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+#define CPU_IDLE_TASK_IS_FP FALSE
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY FALSE
+#define CPU_STACK_GROWS_UP FALSE
+#define CPU_STRUCTURE_ALIGNMENT
+
+/* structures */
+
+/*
+ * Basic integer context for the i386 family.
+ */
+
+typedef struct {
+ unsigned32 eflags; /* extended flags register */
+ void *esp; /* extended stack pointer register */
+ void *ebp; /* extended base pointer register */
+ unsigned32 ebx; /* extended bx register */
+ unsigned32 esi; /* extended source index register */
+ unsigned32 edi; /* extended destination index flags register */
+} Context_Control;
+
+/*
+ * FP context save area for the i387 numeric coprocessors.
+ */
+
+typedef struct {
+ unsigned8 fp_save_area[108]; /* context size area for I80387 */
+ /* 28 bytes for environment */
+} Context_Control_fp;
+
+/*
+ * The following structure defines the set of information saved
+ * on the current stack by RTEMS upon receipt of each interrupt.
+ */
+
+typedef struct {
+ unsigned32 TBD; /* XXX Fix for this CPU */
+} CPU_Interrupt_frame;
+
+/*
+ * The following table contains the information required to configure
+ * the i386 specific parameters.
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ unsigned32 interrupt_stack_size;
+ unsigned32 extra_system_initialization_stack;
+
+ unsigned32 interrupt_table_segment;
+ void *interrupt_table_offset;
+} rtems_cpu_table;
+
+/*
+ * context size area for floating point
+ *
+ * NOTE: This is out of place on the i386 to avoid a forward reference.
+ */
+
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+
+/* variables */
+
+EXTERN unsigned8 _CPU_Null_fp_context[ CPU_CONTEXT_FP_SIZE ];
+EXTERN void *_CPU_Interrupt_stack_low;
+EXTERN void *_CPU_Interrupt_stack_high;
+
+/* constants */
+
+/*
+ * This defines the number of levels and the mask used to pick those
+ * bits out of a thread mode.
+ */
+
+#define CPU_MODES_INTERRUPT_LEVEL 0x00000001 /* interrupt level in mode */
+#define CPU_MODES_INTERRUPT_MASK 0x00000001 /* interrupt level in mode */
+
+/*
+ * extra stack required by system initialization thread
+ */
+
+#define CPU_SYSTEM_INITIALIZATION_THREAD_EXTRA_STACK 1024
+
+/*
+ * i386 family supports 256 distinct vectors.
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
+
+/*
+ * Minimum size of a thread's stack.
+ *
+ * NOTE: 256 bytes is probably too low in most cases.
+ */
+
+#define CPU_STACK_MINIMUM_SIZE 256
+
+/*
+ * i386 is pretty tolerant of alignment. Just put things on 4 byte boundaries.
+ */
+
+#define CPU_ALIGNMENT 4
+#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
+#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * On i386 thread stacks require no further alignment after allocation
+ * from the Workspace.
+ */
+
+#define CPU_STACK_ALIGNMENT 0
+
+/* macros */
+
+/*
+ * ISR handler macros
+ *
+ * These macros perform the following functions:
+ * + disable all maskable CPU interrupts
+ * + restore previous interrupt level (enable)
+ * + temporarily restore interrupts (flash)
+ * + set a particular level
+ */
+
+#define _CPU_ISR_Disable( _level ) i386_disable_interrupts( _level )
+
+#define _CPU_ISR_Enable( _level ) i386_enable_interrupts( _level )
+
+#define _CPU_ISR_Flash( _level ) i386_flash_interrupts( _level )
+
+#define _CPU_ISR_Set_level( _new_level ) \
+ { \
+ if ( _new_level ) asm volatile ( "cli" ); \
+ else asm volatile ( "sti" ); \
+ }
+
+/* end of ISR handler macros */
+
+/*
+ * Context handler macros
+ *
+ * These macros perform the following functions:
+ * + initialize a context area
+ * + restart the current thread
+ * + calculate the initial pointer into a FP context area
+ * + initialize an FP context area
+ */
+
+#define CPU_EFLAGS_INTERRUPTS_ON 0x00003202
+#define CPU_EFLAGS_INTERRUPTS_OFF 0x00003002
+
+#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
+ _isr, _entry_point ) \
+ do { \
+ unsigned32 _stack; \
+ \
+ if ( (_isr) ) (_the_context)->eflags = CPU_EFLAGS_INTERRUPTS_OFF; \
+ else (_the_context)->eflags = CPU_EFLAGS_INTERRUPTS_ON; \
+ \
+ _stack = ((unsigned32)(_stack_base)) + (_size) - 4; \
+ \
+ *((proc_ptr *)(_stack)) = (_entry_point); \
+ (_the_context)->ebp = (void *) _stack; \
+ (_the_context)->esp = (void *) _stack; \
+ } while (0)
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
+
+#define _CPU_Context_Initialize_fp( _fp_area ) \
+ { \
+ unsigned32 *_source = (unsigned32 *) _CPU_Null_fp_context; \
+ unsigned32 *_destination = (unsigned32 *) *(_fp_area); \
+ unsigned32 _index; \
+ \
+ for ( _index=0 ; _index < CPU_CONTEXT_FP_SIZE/4 ; _index++ ) \
+ *_destination++ = *_source++; \
+ }
+
+/* end of Context handler macros */
+
+/*
+ * Fatal Error manager macros
+ *
+ * These macros perform the following functions:
+ * + disable interrupts and halt the CPU
+ */
+
+#define _CPU_Fatal_halt( _error ) \
+ { \
+ asm volatile ( "cli ; \
+ movl %0,%%eax ; \
+ hlt" \
+ : "=r" ((_error)) : "0" ((_error)) \
+ ); \
+ }
+
+/* end of Fatal Error manager macros */
+
+/*
+ * Bitfield handler macros
+ *
+ * These macros perform the following functions:
+ * + scan for the highest numbered (MSB) set in a 16 bit bitfield
+ */
+
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { \
+ register unsigned16 __value_in_register = (_value); \
+ \
+ _output = 0; \
+ \
+ asm volatile ( "bsfw %0,%1 " \
+ : "=r" (__value_in_register), "=r" (_output) \
+ : "0" (__value_in_register), "1" (_output) \
+ ); \
+ }
+
+/* end of Bitfield handler macros */
+
+/*
+ * Priority handler macros
+ *
+ * These macros perform the following functions:
+ * + return a mask with the bit for this major/minor portion of
+ * of thread priority set.
+ * + translate the bit number returned by "Bitfield_find_first_bit"
+ * into an index into the thread ready chain bit maps
+ */
+
+#define _CPU_Priority_Mask( _bit_number ) \
+ ( 1 << (_bit_number) )
+
+#define _CPU_Priority_Bits_index( _priority ) \
+ (_priority)
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ */
+
+void _CPU_ISR_install_vector(
+ unsigned32 vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generallu used only to restart self in an
+ * efficient manner and avoid stack conflicts.
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/c/src/exec/score/cpu/i386/cpu_asm.s b/c/src/exec/score/cpu/i386/cpu_asm.s
new file mode 100644
index 0000000000..121b4409d9
--- /dev/null
+++ b/c/src/exec/score/cpu/i386/cpu_asm.s
@@ -0,0 +1,654 @@
+/* cpu_asm.s
+ *
+ * This file contains all assembly code for the Intel i386 implementation
+ * of RTEMS.
+ *
+ * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
+ * On-Line Applications Research Corporation (OAR).
+ * All rights assigned to U.S. Government, 1994.
+ *
+ * This material may be reproduced by or for the U.S. Government pursuant
+ * to the copyright license under the clause at DFARS 252.227-7013. This
+ * notice must appear in all copies of this file and its derivatives.
+ *
+ * $Id$
+ */
+
+#include <asm.h>
+
+/*
+ * Format of i386 Register structure
+ */
+
+.set REG_EFLAGS, 0
+.set REG_ESP, REG_EFLAGS + 4
+.set REG_EBP, REG_ESP + 4
+.set REG_EBX, REG_EBP + 4
+.set REG_ESI, REG_EBX + 4
+.set REG_EDI, REG_ESI + 4
+.set SIZE_REGS, REG_EDI + 4
+
+ BEGIN_CODE
+
+/*
+ * void _CPU_Context_switch( run_context, heir_context )
+ *
+ * This routine performs a normal non-FP context.
+ */
+
+ .align 2
+ PUBLIC (_CPU_Context_switch)
+
+.set RUNCONTEXT_ARG, 4 # save context argument
+.set HEIRCONTEXT_ARG, 8 # restore context argument
+
+SYM (_CPU_Context_switch):
+ movl RUNCONTEXT_ARG(esp),eax # eax = running threads context
+ pushf # push eflags
+ popl REG_EFLAGS(eax) # save eflags
+ movl esp,REG_ESP(eax) # save stack pointer
+ movl ebp,REG_EBP(eax) # save base pointer
+ movl ebx,REG_EBX(eax) # save ebx
+ movl esi,REG_ESI(eax) # save source register
+ movl edi,REG_EDI(eax) # save destination register
+
+ movl HEIRCONTEXT_ARG(esp),eax # eax = heir threads context
+
+restore:
+ pushl REG_EFLAGS(eax) # push eflags
+ popf # restore eflags
+ movl REG_ESP(eax),esp # restore stack pointer
+ movl REG_EBP(eax),ebp # restore base pointer
+ movl REG_EBX(eax),ebx # restore ebx
+ movl REG_ESI(eax),esi # restore source register
+ movl REG_EDI(eax),edi # restore destination register
+ ret
+
+/*
+ * NOTE: May be unnecessary to reload some registers.
+ */
+
+/*
+ * void _CPU_Context_restore( new_context )
+ *
+ * This routine performs a normal non-FP context.
+ */
+
+ PUBLIC (_CPU_Context_restore)
+
+.set NEWCONTEXT_ARG, 4 # context to restore argument
+
+SYM (_CPU_Context_restore):
+
+ movl NEWCONTEXT_ARG(esp),eax # eax = running threads context
+ jmp restore
+
+/*PAGE
+ * void _CPU_Context_save_fp_context( &fp_context_ptr )
+ * void _CPU_Context_restore_fp_context( &fp_context_ptr )
+ *
+ * This section is used to context switch an i80287, i80387,
+ * the built-in coprocessor or the i80486 or compatible.
+ */
+
+.set FPCONTEXT_ARG, 4 # FP context argument
+
+ .align 2
+ PUBLIC (_CPU_Context_save_fp)
+SYM (_CPU_Context_save_fp):
+ movl FPCONTEXT_ARG(esp),eax # eax = &ptr to FP context area
+ movl (eax),eax # eax = FP context area
+ fsave (eax) # save FP context
+ ret
+
+ .align 2
+ PUBLIC (_CPU_Context_restore_fp)
+SYM (_CPU_Context_restore_fp):
+ movl FPCONTEXT_ARG(esp),eax # eax = &ptr to FP context area
+ movl (eax),eax # eax = FP context area
+ frstor (eax) # restore FP context
+ ret
+
+/*PAGE
+ * void _ISR_Handler()
+ *
+ * This routine provides the RTEMS interrupt management.
+ *
+ * NOTE:
+ * Upon entry, the stack will contain a stack frame back to the
+ * interrupted task. If dispatching is enabled, this is the
+ * outer most interrupt, and (a context switch is necessary or
+ * the current task has signals), then set up the stack to
+ * transfer control to the interrupt dispatcher.
+ */
+
+.set SET_SEGMENT_REGISTERS_IN_INTERRUPT, 0
+
+.set SAVED_REGS , 32 # space consumed by saved regs
+.set EIP_OFFSET , SAVED_REGS # offset of tasks eip
+.set CS_OFFSET , EIP_OFFSET+4 # offset of tasks code segment
+.set EFLAGS_OFFSET , CS_OFFSET+4 # offset of tasks eflags
+
+ .align 2
+ PUBLIC (_ISR_Handler)
+
+SYM (_ISR_Handler):
+ /*
+ * Before this was point is reached the vectors unique
+ * entry point did the following:
+ *
+ * 1. saved all registers with a "pusha"
+ * 2. put the vector number in eax.
+ *
+ * BEGINNING OF ESTABLISH SEGMENTS
+ *
+ * WARNING: If an interrupt can occur when the segments are
+ * not correct, then this is where we should establish
+ * the segments. In addition to establishing the
+ * segments, it may be necessary to establish a stack
+ * in the current data area on the outermost interrupt.
+ *
+ * NOTE: If the previous values of the segment registers are
+ * pushed, do not forget to adjust SAVED_REGS.
+ *
+ * NOTE: Make sure the exit code which restores these
+ * when this type of code is needed.
+ */
+
+ /***** ESTABLISH SEGMENTS CODE GOES HERE ******/
+
+ /*
+ * END OF ESTABLISH SEGMENTS
+ */
+
+ /*
+ * Now switch stacks if necessary
+ */
+
+ movl esp, edx # edx = previous stack pointer
+ cmpl $0, SYM (_ISR_Nest_level) # is this the outermost interrupt?
+ jne nested # No, then continue
+ movl SYM (_CPU_Interrupt_stack_high), esp
+
+ /*
+ * We want to insure that the old stack pointer is on the
+ * stack we will be on at the end of the ISR when we restore it.
+ * By saving it on every interrupt, all we have to do is pop it
+ * near the end of every interrupt.
+ */
+
+nested:
+ pushl edx # save the previous stack pointer
+ incl SYM (_ISR_Nest_level) # one nest level deeper
+ incl SYM (_Thread_Dispatch_disable_level) # disable multitasking
+
+ # EAX is preloaded with the vector number.
+ push eax # push vector number
+ mov SYM (_ISR_Vector_table) (,eax,4),eax
+ # eax = Users handler
+ call eax # invoke user ISR
+ pop eax # eax = vector number
+
+ decl SYM (_ISR_Nest_level) # one less ISR nest level
+ # If interrupts are nested,
+ # then dispatching is disabled
+
+ decl SYM (_Thread_Dispatch_disable_level)
+ # unnest multitasking
+ # Is dispatch disabled
+ jne exit # Yes, then exit
+
+ cmpl $0, SYM (_Context_Switch_necessary)
+ # Is task switch necessary?
+ jne bframe # Yes, then build stack
+
+ cmpl $0, SYM (_ISR_Signals_to_thread_executing)
+ # signals sent to Run_thread
+ # while in interrupt handler?
+ je exit # No, exit
+
+bframe:
+ cli # DISABLE INTERRUPTS!!
+ popl esp # restore the stack pointer
+ movl $0, SYM (_ISR_Signals_to_thread_executing)
+ # push the isf for Isr_dispatch
+ push EFLAGS_OFFSET(esp) # push tasks eflags
+ push cs # cs of Isr_dispatch
+ push $ SYM (_ISR_Dispatch) # entry point
+ iret
+
+exit:
+ cli # DISABLE INTERRUPTS!!
+ popl esp # restore the stack pointer
+
+ /*
+ * BEGINNING OF DE-ESTABLISH SEGMENTS
+ *
+ * NOTE: Make sure there is code here if code is added to
+ * load the segment registers.
+ *
+ */
+
+ /******* DE-ESTABLISH SEGMENTS CODE GOES HERE ********/
+
+ /*
+ * END OF DE-ESTABLISH SEGMENTS
+ */
+
+ popa # restore general registers
+ iret
+
+/*PAGE
+ * Distinct Interrupt Entry Points
+ *
+ * The following macro and the 256 instantiations of the macro
+ * are necessary to determine which interrupt vector occurred.
+ * The following macro allows a unique entry point to be defined
+ * for each vector.
+ *
+ * NOTE: There are not spaces around the vector number argument
+ * to the DISTINCT_INTERRUPT_ENTRY macro because m4 will
+ * undesirably generate the symbol "_Isr_handler_ N"
+ * instead of "_Isr_handler_N" like we want.
+ */
+
+#define DISTINCT_INTERRUPT_ENTRY(_vector) \
+ .align 16 ; \
+ PUBLIC (_ISR_Handler_ ## _vector ) ; \
+SYM (_ISR_Handler_ ## _vector ): \
+ pusha ; \
+ xor eax, eax ; \
+ movb $ ## _vector, al ; \
+ jmp SYM (_ISR_Handler) ;
+
+DISTINCT_INTERRUPT_ENTRY(0)
+DISTINCT_INTERRUPT_ENTRY(1)
+DISTINCT_INTERRUPT_ENTRY(2)
+DISTINCT_INTERRUPT_ENTRY(3)
+DISTINCT_INTERRUPT_ENTRY(4)
+DISTINCT_INTERRUPT_ENTRY(5)
+DISTINCT_INTERRUPT_ENTRY(6)
+DISTINCT_INTERRUPT_ENTRY(7)
+DISTINCT_INTERRUPT_ENTRY(8)
+DISTINCT_INTERRUPT_ENTRY(9)
+DISTINCT_INTERRUPT_ENTRY(10)
+DISTINCT_INTERRUPT_ENTRY(11)
+DISTINCT_INTERRUPT_ENTRY(12)
+DISTINCT_INTERRUPT_ENTRY(13)
+DISTINCT_INTERRUPT_ENTRY(14)
+DISTINCT_INTERRUPT_ENTRY(15)
+DISTINCT_INTERRUPT_ENTRY(16)
+DISTINCT_INTERRUPT_ENTRY(17)
+DISTINCT_INTERRUPT_ENTRY(18)
+DISTINCT_INTERRUPT_ENTRY(19)
+DISTINCT_INTERRUPT_ENTRY(20)
+DISTINCT_INTERRUPT_ENTRY(21)
+DISTINCT_INTERRUPT_ENTRY(22)
+DISTINCT_INTERRUPT_ENTRY(23)
+DISTINCT_INTERRUPT_ENTRY(24)
+DISTINCT_INTERRUPT_ENTRY(25)
+DISTINCT_INTERRUPT_ENTRY(26)
+DISTINCT_INTERRUPT_ENTRY(27)
+DISTINCT_INTERRUPT_ENTRY(28)
+DISTINCT_INTERRUPT_ENTRY(29)
+DISTINCT_INTERRUPT_ENTRY(30)
+DISTINCT_INTERRUPT_ENTRY(31)
+DISTINCT_INTERRUPT_ENTRY(32)
+DISTINCT_INTERRUPT_ENTRY(33)
+DISTINCT_INTERRUPT_ENTRY(34)
+DISTINCT_INTERRUPT_ENTRY(35)
+DISTINCT_INTERRUPT_ENTRY(36)
+DISTINCT_INTERRUPT_ENTRY(37)
+DISTINCT_INTERRUPT_ENTRY(38)
+DISTINCT_INTERRUPT_ENTRY(39)
+DISTINCT_INTERRUPT_ENTRY(40)
+DISTINCT_INTERRUPT_ENTRY(41)
+DISTINCT_INTERRUPT_ENTRY(42)
+DISTINCT_INTERRUPT_ENTRY(43)
+DISTINCT_INTERRUPT_ENTRY(44)
+DISTINCT_INTERRUPT_ENTRY(45)
+DISTINCT_INTERRUPT_ENTRY(46)
+DISTINCT_INTERRUPT_ENTRY(47)
+DISTINCT_INTERRUPT_ENTRY(48)
+DISTINCT_INTERRUPT_ENTRY(49)
+DISTINCT_INTERRUPT_ENTRY(50)
+DISTINCT_INTERRUPT_ENTRY(51)
+DISTINCT_INTERRUPT_ENTRY(52)
+DISTINCT_INTERRUPT_ENTRY(53)
+DISTINCT_INTERRUPT_ENTRY(54)
+DISTINCT_INTERRUPT_ENTRY(55)
+DISTINCT_INTERRUPT_ENTRY(56)
+DISTINCT_INTERRUPT_ENTRY(57)
+DISTINCT_INTERRUPT_ENTRY(58)
+DISTINCT_INTERRUPT_ENTRY(59)
+DISTINCT_INTERRUPT_ENTRY(60)
+DISTINCT_INTERRUPT_ENTRY(61)
+DISTINCT_INTERRUPT_ENTRY(62)
+DISTINCT_INTERRUPT_ENTRY(63)
+DISTINCT_INTERRUPT_ENTRY(64)
+DISTINCT_INTERRUPT_ENTRY(65)
+DISTINCT_INTERRUPT_ENTRY(66)
+DISTINCT_INTERRUPT_ENTRY(67)
+DISTINCT_INTERRUPT_ENTRY(68)
+DISTINCT_INTERRUPT_ENTRY(69)
+DISTINCT_INTERRUPT_ENTRY(70)
+DISTINCT_INTERRUPT_ENTRY(71)
+DISTINCT_INTERRUPT_ENTRY(72)
+DISTINCT_INTERRUPT_ENTRY(73)
+DISTINCT_INTERRUPT_ENTRY(74)
+DISTINCT_INTERRUPT_ENTRY(75)
+DISTINCT_INTERRUPT_ENTRY(76)
+DISTINCT_INTERRUPT_ENTRY(77)
+DISTINCT_INTERRUPT_ENTRY(78)
+DISTINCT_INTERRUPT_ENTRY(79)
+DISTINCT_INTERRUPT_ENTRY(80)
+DISTINCT_INTERRUPT_ENTRY(81)
+DISTINCT_INTERRUPT_ENTRY(82)
+DISTINCT_INTERRUPT_ENTRY(83)
+DISTINCT_INTERRUPT_ENTRY(84)
+DISTINCT_INTERRUPT_ENTRY(85)
+DISTINCT_INTERRUPT_ENTRY(86)
+DISTINCT_INTERRUPT_ENTRY(87)
+DISTINCT_INTERRUPT_ENTRY(88)
+DISTINCT_INTERRUPT_ENTRY(89)
+DISTINCT_INTERRUPT_ENTRY(90)
+DISTINCT_INTERRUPT_ENTRY(91)
+DISTINCT_INTERRUPT_ENTRY(92)
+DISTINCT_INTERRUPT_ENTRY(93)
+DISTINCT_INTERRUPT_ENTRY(94)
+DISTINCT_INTERRUPT_ENTRY(95)
+DISTINCT_INTERRUPT_ENTRY(96)
+DISTINCT_INTERRUPT_ENTRY(97)
+DISTINCT_INTERRUPT_ENTRY(98)
+DISTINCT_INTERRUPT_ENTRY(99)
+DISTINCT_INTERRUPT_ENTRY(100)
+DISTINCT_INTERRUPT_ENTRY(101)
+DISTINCT_INTERRUPT_ENTRY(102)
+DISTINCT_INTERRUPT_ENTRY(103)
+DISTINCT_INTERRUPT_ENTRY(104)
+DISTINCT_INTERRUPT_ENTRY(105)
+DISTINCT_INTERRUPT_ENTRY(106)
+DISTINCT_INTERRUPT_ENTRY(107)
+DISTINCT_INTERRUPT_ENTRY(108)
+DISTINCT_INTERRUPT_ENTRY(109)
+DISTINCT_INTERRUPT_ENTRY(110)
+DISTINCT_INTERRUPT_ENTRY(111)
+DISTINCT_INTERRUPT_ENTRY(112)
+DISTINCT_INTERRUPT_ENTRY(113)
+DISTINCT_INTERRUPT_ENTRY(114)
+DISTINCT_INTERRUPT_ENTRY(115)
+DISTINCT_INTERRUPT_ENTRY(116)
+DISTINCT_INTERRUPT_ENTRY(117)
+DISTINCT_INTERRUPT_ENTRY(118)
+DISTINCT_INTERRUPT_ENTRY(119)
+DISTINCT_INTERRUPT_ENTRY(120)
+DISTINCT_INTERRUPT_ENTRY(121)
+DISTINCT_INTERRUPT_ENTRY(122)
+DISTINCT_INTERRUPT_ENTRY(123)
+DISTINCT_INTERRUPT_ENTRY(124)
+DISTINCT_INTERRUPT_ENTRY(125)
+DISTINCT_INTERRUPT_ENTRY(126)
+DISTINCT_INTERRUPT_ENTRY(127)
+DISTINCT_INTERRUPT_ENTRY(128)
+DISTINCT_INTERRUPT_ENTRY(129)
+DISTINCT_INTERRUPT_ENTRY(130)
+DISTINCT_INTERRUPT_ENTRY(131)
+DISTINCT_INTERRUPT_ENTRY(132)
+DISTINCT_INTERRUPT_ENTRY(133)
+DISTINCT_INTERRUPT_ENTRY(134)
+DISTINCT_INTERRUPT_ENTRY(135)
+DISTINCT_INTERRUPT_ENTRY(136)
+DISTINCT_INTERRUPT_ENTRY(137)
+DISTINCT_INTERRUPT_ENTRY(138)
+DISTINCT_INTERRUPT_ENTRY(139)
+DISTINCT_INTERRUPT_ENTRY(140)
+DISTINCT_INTERRUPT_ENTRY(141)
+DISTINCT_INTERRUPT_ENTRY(142)
+DISTINCT_INTERRUPT_ENTRY(143)
+DISTINCT_INTERRUPT_ENTRY(144)
+DISTINCT_INTERRUPT_ENTRY(145)
+DISTINCT_INTERRUPT_ENTRY(146)
+DISTINCT_INTERRUPT_ENTRY(147)
+DISTINCT_INTERRUPT_ENTRY(148)
+DISTINCT_INTERRUPT_ENTRY(149)
+DISTINCT_INTERRUPT_ENTRY(150)
+DISTINCT_INTERRUPT_ENTRY(151)
+DISTINCT_INTERRUPT_ENTRY(152)
+DISTINCT_INTERRUPT_ENTRY(153)
+DISTINCT_INTERRUPT_ENTRY(154)
+DISTINCT_INTERRUPT_ENTRY(155)
+DISTINCT_INTERRUPT_ENTRY(156)
+DISTINCT_INTERRUPT_ENTRY(157)
+DISTINCT_INTERRUPT_ENTRY(158)
+DISTINCT_INTERRUPT_ENTRY(159)
+DISTINCT_INTERRUPT_ENTRY(160)
+DISTINCT_INTERRUPT_ENTRY(161)
+DISTINCT_INTERRUPT_ENTRY(162)
+DISTINCT_INTERRUPT_ENTRY(163)
+DISTINCT_INTERRUPT_ENTRY(164)
+DISTINCT_INTERRUPT_ENTRY(165)
+DISTINCT_INTERRUPT_ENTRY(166)
+DISTINCT_INTERRUPT_ENTRY(167)
+DISTINCT_INTERRUPT_ENTRY(168)
+DISTINCT_INTERRUPT_ENTRY(169)
+DISTINCT_INTERRUPT_ENTRY(170)
+DISTINCT_INTERRUPT_ENTRY(171)
+DISTINCT_INTERRUPT_ENTRY(172)
+DISTINCT_INTERRUPT_ENTRY(173)
+DISTINCT_INTERRUPT_ENTRY(174)
+DISTINCT_INTERRUPT_ENTRY(175)
+DISTINCT_INTERRUPT_ENTRY(176)
+DISTINCT_INTERRUPT_ENTRY(177)
+DISTINCT_INTERRUPT_ENTRY(178)
+DISTINCT_INTERRUPT_ENTRY(179)
+DISTINCT_INTERRUPT_ENTRY(180)
+DISTINCT_INTERRUPT_ENTRY(181)
+DISTINCT_INTERRUPT_ENTRY(182)
+DISTINCT_INTERRUPT_ENTRY(183)
+DISTINCT_INTERRUPT_ENTRY(184)
+DISTINCT_INTERRUPT_ENTRY(185)
+DISTINCT_INTERRUPT_ENTRY(186)
+DISTINCT_INTERRUPT_ENTRY(187)
+DISTINCT_INTERRUPT_ENTRY(188)
+DISTINCT_INTERRUPT_ENTRY(189)
+DISTINCT_INTERRUPT_ENTRY(190)
+DISTINCT_INTERRUPT_ENTRY(191)
+DISTINCT_INTERRUPT_ENTRY(192)
+DISTINCT_INTERRUPT_ENTRY(193)
+DISTINCT_INTERRUPT_ENTRY(194)
+DISTINCT_INTERRUPT_ENTRY(195)
+DISTINCT_INTERRUPT_ENTRY(196)
+DISTINCT_INTERRUPT_ENTRY(197)
+DISTINCT_INTERRUPT_ENTRY(198)
+DISTINCT_INTERRUPT_ENTRY(199)
+DISTINCT_INTERRUPT_ENTRY(200)
+DISTINCT_INTERRUPT_ENTRY(201)
+DISTINCT_INTERRUPT_ENTRY(202)
+DISTINCT_INTERRUPT_ENTRY(203)
+DISTINCT_INTERRUPT_ENTRY(204)
+DISTINCT_INTERRUPT_ENTRY(205)
+DISTINCT_INTERRUPT_ENTRY(206)
+DISTINCT_INTERRUPT_ENTRY(207)
+DISTINCT_INTERRUPT_ENTRY(208)
+DISTINCT_INTERRUPT_ENTRY(209)
+DISTINCT_INTERRUPT_ENTRY(210)
+DISTINCT_INTERRUPT_ENTRY(211)
+DISTINCT_INTERRUPT_ENTRY(212)
+DISTINCT_INTERRUPT_ENTRY(213)
+DISTINCT_INTERRUPT_ENTRY(214)
+DISTINCT_INTERRUPT_ENTRY(215)
+DISTINCT_INTERRUPT_ENTRY(216)
+DISTINCT_INTERRUPT_ENTRY(217)
+DISTINCT_INTERRUPT_ENTRY(218)
+DISTINCT_INTERRUPT_ENTRY(219)
+DISTINCT_INTERRUPT_ENTRY(220)
+DISTINCT_INTERRUPT_ENTRY(221)
+DISTINCT_INTERRUPT_ENTRY(222)
+DISTINCT_INTERRUPT_ENTRY(223)
+DISTINCT_INTERRUPT_ENTRY(224)
+DISTINCT_INTERRUPT_ENTRY(225)
+DISTINCT_INTERRUPT_ENTRY(226)
+DISTINCT_INTERRUPT_ENTRY(227)
+DISTINCT_INTERRUPT_ENTRY(228)
+DISTINCT_INTERRUPT_ENTRY(229)
+DISTINCT_INTERRUPT_ENTRY(230)
+DISTINCT_INTERRUPT_ENTRY(231)
+DISTINCT_INTERRUPT_ENTRY(232)
+DISTINCT_INTERRUPT_ENTRY(233)
+DISTINCT_INTERRUPT_ENTRY(234)
+DISTINCT_INTERRUPT_ENTRY(235)
+DISTINCT_INTERRUPT_ENTRY(236)
+DISTINCT_INTERRUPT_ENTRY(237)
+DISTINCT_INTERRUPT_ENTRY(238)
+DISTINCT_INTERRUPT_ENTRY(239)
+DISTINCT_INTERRUPT_ENTRY(240)
+DISTINCT_INTERRUPT_ENTRY(241)
+DISTINCT_INTERRUPT_ENTRY(242)
+DISTINCT_INTERRUPT_ENTRY(243)
+DISTINCT_INTERRUPT_ENTRY(244)
+DISTINCT_INTERRUPT_ENTRY(245)
+DISTINCT_INTERRUPT_ENTRY(246)
+DISTINCT_INTERRUPT_ENTRY(247)
+DISTINCT_INTERRUPT_ENTRY(248)
+DISTINCT_INTERRUPT_ENTRY(249)
+DISTINCT_INTERRUPT_ENTRY(250)
+DISTINCT_INTERRUPT_ENTRY(251)
+DISTINCT_INTERRUPT_ENTRY(252)
+DISTINCT_INTERRUPT_ENTRY(253)
+DISTINCT_INTERRUPT_ENTRY(254)
+DISTINCT_INTERRUPT_ENTRY(255)
+
+/*PAGE
+ * void _ISR_Dispatch()
+ *
+ * Entry point from the outermost interrupt service routine exit.
+ * The current stack is the supervisor mode stack.
+ */
+
+ PUBLIC (_ISR_Dispatch)
+SYM (_ISR_Dispatch):
+
+ call SYM (_Thread_Dispatch) # invoke Dispatcher
+
+ /*
+ * BEGINNING OF DE-ESTABLISH SEGMENTS
+ *
+ * NOTE: Make sure there is code here if code is added to
+ * load the segment registers.
+ *
+ */
+
+ /***** DE-ESTABLISH SEGMENTS CODE GOES HERE ****/
+
+ /*
+ * END OF DE-ESTABLISH SEGMENTS
+ */
+
+ popa # restore general registers
+ iret # return to interrupted thread
+
+/*PAGE
+ *
+ * void i386_Install_idt(
+ * unsigned32 source_offset,
+ * unsigned16 destination_segment,
+ * unsigned32 destination_offset
+ * );
+ */
+
+ .align 2
+ PUBLIC (i386_Install_idt)
+
+.set INSTALL_IDT_SAVED_REGS, 8
+
+.set SOURCE_OFFSET_ARG, INSTALL_IDT_SAVED_REGS + 4
+.set DESTINATION_SEGMENT_ARG, INSTALL_IDT_SAVED_REGS + 8
+.set DESTINATION_OFFSET_ARG, INSTALL_IDT_SAVED_REGS + 12
+
+SYM (i386_Install_idt):
+ push esi
+ push edi
+
+ movl SOURCE_OFFSET_ARG(esp),esi
+ movl DESTINATION_OFFSET_ARG(esp),edi
+
+ pushf # save flags
+ cli # DISABLE INTERRUPTS!!!
+
+ movw DESTINATION_SEGMENT_ARG+4(esp),ax
+ push es # save es
+ movw ax,es
+ movsl # copy 1st half of IDT entry
+ movsl # copy 2nd half of IDT entry
+ pop es # restore es
+
+ popf # ENABLE INTERRUPTS!!!
+
+ pop edi
+ pop esi
+ ret
+
+/*
+ * void *i386_Logical_to_physical(
+ * rtems_unsigned16 segment,
+ * void *address
+ * );
+ *
+ * Returns thirty-two bit physical address for segment:address.
+ */
+
+.set SEGMENT_ARG, 4
+.set ADDRESS_ARG, 8
+
+ PUBLIC (i386_Logical_to_physical)
+
+SYM (i386_Logical_to_physical):
+
+ xorl eax,eax # clear eax
+ movzwl SEGMENT_ARG(esp),ecx # ecx = segment value
+ movl $ SYM (_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 *i386_Physical_to_logical(
+ * rtems_unsigned16 segment,
+ * void *address
+ * );
+ *
+ * Returns thirty-two bit physical address for segment:address.
+ */
+
+/*
+ *.set SEGMENT_ARG, 4
+ *.set ADDRESS_ARG, 8 -- use sets from above
+ */
+
+ PUBLIC (i386_Physical_to_logical)
+
+SYM (i386_Physical_to_logical):
+ xorl eax,eax # clear eax
+ movzwl SEGMENT_ARG(esp),ecx # ecx = segment value
+ movl $ SYM (_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
+
+END_CODE
+
+END
diff --git a/c/src/exec/score/cpu/i386/i386.h b/c/src/exec/score/cpu/i386/i386.h
new file mode 100644
index 0000000000..a8db759984
--- /dev/null
+++ b/c/src/exec/score/cpu/i386/i386.h
@@ -0,0 +1,493 @@
+/* i386.h
+ *
+ * This include file contains information pertaining to the Intel
+ * i386 processor.
+ *
+ * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
+ * On-Line Applications Research Corporation (OAR).
+ * All rights assigned to U.S. Government, 1994.
+ *
+ * This material may be reproduced by or for the U.S. Government pursuant
+ * to the copyright license under the clause at DFARS 252.227-7013. This
+ * notice must appear in all copies of this file and its derivatives.
+ *
+ * $Id$
+ */
+
+#ifndef __i386_h
+#define __i386_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The following define the CPU Family and Model within the family
+ *
+ * NOTE: The string "REPLACE_THIS_WITH_THE_CPU_MODEL" is replaced
+ * with the name of the appropriate macro for this target CPU.
+ */
+
+#define i386
+#define REPLACE_THIS_WITH_THE_CPU_MODEL
+#define REPLACE_THIS_WITH_THE_BSP
+
+/*
+ * This section contains the information required to build
+ * RTEMS for a particular member of the Intel i386
+ * family when executing in protected mode. It does
+ * this by setting variables to indicate which implementation
+ * dependent features are present in a particular member
+ * of the family.
+ *
+ * Currently recognized:
+ * i386_fp (i386 DX or SX w/i387)
+ * i386_fp (i386 DX or SX w/o i387)
+ * i486dx
+ * i486sx
+ * pentium
+ *
+ * Floating point is the only feature which currently varies. Eventually
+ * the i486-plus level instruction for endian swapping should be added
+ * to this feature list.
+ */
+
+#if defined(i386_fp)
+
+#define RTEMS_MODEL_NAME "i386 with i387"
+#define I386_HAS_FPU 1
+
+#elif defined(i386_nofp)
+
+#define RTEMS_MODEL_NAME "i386 w/o i387"
+#define I386_HAS_FPU 1
+
+#elif defined(i486dx)
+
+#define RTEMS_MODEL_NAME "i486dx"
+#define I386_HAS_FPU 1
+
+#elif defined(i486sx)
+
+#define RTEMS_MODEL_NAME "i486sx"
+#define I386_HAS_FPU 0
+
+#elif defined(pentium)
+
+#define RTEMS_MODEL_NAME "Pentium"
+#define I386_HAS_FPU 1
+
+#else
+
+#error "Unsupported CPU Model"
+
+#endif
+
+/*
+ * Define the name of the CPU family.
+ */
+
+#define CPU_NAME "Intel i386"
+
+#ifndef ASM
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* 8-bit unsigned integer */
+typedef unsigned short unsigned16; /* 16-bit unsigned integer */
+typedef unsigned int unsigned32; /* 32-bit unsigned integer */
+typedef unsigned long long unsigned64; /* 64-bit unsigned integer */
+
+typedef unsigned16 Priority_Bit_map_control;
+
+typedef unsigned char signed8; /* 8-bit signed integer */
+typedef unsigned short signed16; /* 16-bit signed integer */
+typedef unsigned int signed32; /* 32-bit signed integer */
+typedef long long signed64; /* 64-bit signed integer */
+
+typedef unsigned32 boolean; /* Boolean value */
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+/*
+ * Structure which makes it easier to deal with LxDT and SxDT instructions.
+ */
+
+typedef struct {
+ unsigned short limit;
+ unsigned short physical_address[ 2 ];
+} i386_DTR_load_save_format;
+
+/* See Chapter 5 - Memory Management in i386 manual */
+
+typedef struct {
+ unsigned short limit_0_15;
+ unsigned short base_0_15;
+ unsigned char base_16_23;
+ unsigned char type_dt_dpl_p;
+ unsigned char limit_16_19_granularity;
+ unsigned char base_24_31;
+} i386_GDT_slot;
+
+/* See Chapter 9 - Exceptions and Interrupts in i386 manual
+ *
+ * NOTE: This is the IDT entry for interrupt gates ONLY.
+ */
+
+typedef struct {
+ unsigned short offset_0_15;
+ unsigned short segment_selector;
+ unsigned char reserved;
+ unsigned char p_dpl;
+ unsigned short offset_16_31;
+} i386_IDT_slot;
+
+typedef void ( *i386_isr )( void );
+
+#define i386_disable_interrupts( _level ) \
+ { \
+ _level = 0; /* avoids warnings */ \
+ asm volatile ( "pushf ; \
+ cli ; \
+ pop %0" \
+ : "=r" ((_level)) : "0" ((_level)) \
+ ); \
+ }
+
+#define i386_enable_interrupts( _level ) \
+ { \
+ asm volatile ( "push %0 ; \
+ popf" \
+ : "=r" ((_level)) : "0" ((_level)) \
+ ); \
+ }
+
+#define i386_flash_interrupts( _level ) \
+ { \
+ asm volatile ( "push %0 ; \
+ popf ; \
+ cli" \
+ : "=r" ((_level)) : "0" ((_level)) \
+ ); \
+ }
+
+/*
+ * The following routine swaps the endian format of an unsigned int.
+ * It must be static so it can be referenced indirectly.
+ */
+
+static inline unsigned int i386_swap_U32(
+ unsigned int value
+)
+{
+ asm volatile( "rorw $8,%%ax;"
+ "rorl $16,%0;"
+ "rorw $8,%%ax" : "=a" (value) : "0" (value) );
+
+ return( value );
+}
+
+/*
+ * Segment Access Routines
+ *
+ * NOTE: Unfortunately, these are still static inlines even when the
+ * "macro" implementation of the generic code is used.
+ */
+
+static inline unsigned short i386_get_cs()
+{
+ register unsigned short segment = 0;
+
+ asm volatile ( "movw %%cs,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline unsigned short i386_get_ds()
+{
+ register unsigned short segment = 0;
+
+ asm volatile ( "movw %%ds,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline unsigned short i386_get_es()
+{
+ register unsigned short segment = 0;
+
+ asm volatile ( "movw %%es,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline unsigned short i386_get_ss()
+{
+ register unsigned short segment = 0;
+
+ asm volatile ( "movw %%ss,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline unsigned short i386_get_fs()
+{
+ register unsigned short segment = 0;
+
+ asm volatile ( "movw %%fs,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline unsigned short i386_get_gs()
+{
+ register unsigned short segment = 0;
+
+ asm volatile ( "movw %%gs,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+/*
+ * IO Port Access Routines
+ */
+
+#define i386_outport_byte( _port, _value ) \
+ { register unsigned short __port = _port; \
+ register unsigned char __value = _value; \
+ \
+ asm volatile ( "outb %0,%1" : "=a" (__value), "=d" (__port) \
+ : "0" (__value), "1" (__port) \
+ ); \
+ }
+
+#define i386_outport_word( _port, _value ) \
+ { register unsigned short __port = _port; \
+ register unsigned short __value = _value; \
+ \
+ asm volatile ( "outw %0,%1" : "=a" (__value), "=d" (__port) \
+ : "0" (__value), "1" (__port) \
+ ); \
+ }
+
+#define i386_outport_long( _port, _value ) \
+ { register unsigned short __port = _port; \
+ register unsigned int __value = _value; \
+ \
+ asm volatile ( "outl %0,%1" : "=a" (__value), "=d" (__port) \
+ : "0" (__value), "1" (__port) \
+ ); \
+ }
+
+#define i386_inport_byte( _port, _value ) \
+ { register unsigned short __port = _port; \
+ register unsigned char __value = 0; \
+ \
+ asm volatile ( "inb %1,%0" : "=a" (__value), "=d" (__port) \
+ : "0" (__value), "1" (__port) \
+ ); \
+ _value = __value; \
+ }
+
+#define i386_inport_word( _port, _value ) \
+ { register unsigned short __port = _port; \
+ register unsigned short __value = 0; \
+ \
+ asm volatile ( "inw %1,%0" : "=a" (__value), "=d" (__port) \
+ : "0" (__value), "1" (__port) \
+ ); \
+ _value = __value; \
+ }
+
+#define i386_inport_long( _port, _value ) \
+ { register unsigned short __port = _port; \
+ register unsigned int __value = 0; \
+ \
+ asm volatile ( "inl %1,%0" : "=a" (__value), "=d" (__port) \
+ : "0" (__value), "1" (__port) \
+ ); \
+ _value = __value; \
+ }
+
+/*
+ * Descriptor Table helper routines
+ */
+
+
+#define i386_get_GDTR( _gdtr_address ) \
+ { \
+ void *_gdtr = (_gdtr_address); \
+ \
+ asm volatile( "sgdt (%0)" : "=r" (_gdtr) : "0" (_gdtr) ); \
+ }
+
+#define i386_get_GDT_slot( _gdtr_base, _segment, _slot_address ) \
+ { \
+ register unsigned int _gdt_slot = (_gdtr_base) + (_segment); \
+ register volatile void *_slot = (_slot_address); \
+ register unsigned int _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 i386_set_GDT_slot( _gdtr_base, _segment, _slot_address ) \
+ { \
+ register unsigned int _gdt_slot = (_gdtr_base) + (_segment); \
+ register volatile void *_slot = (_slot_address); \
+ register unsigned int _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 i386_set_segment(
+ unsigned short segment,
+ unsigned int base,
+ unsigned int limit
+)
+{
+ i386_DTR_load_save_format gdtr;
+ volatile i386_GDT_slot Gdt_slot;
+ volatile i386_GDT_slot *gdt_slot = &Gdt_slot;
+ unsigned short tmp_segment = 0;
+ unsigned int limit_adjusted;
+
+ /* load physical address of the GDT */
+
+ i386_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);
+
+ i386_set_GDT_slot(
+ gdtr.physical_address[0] + (gdtr.physical_address[1] << 16),
+ 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)
+ );
+
+}
+
+/* routines */
+
+/*
+ * i386_Logical_to_physical
+ *
+ * Converts logical address to physical address.
+ */
+
+void *i386_Logical_to_physical(
+ unsigned short segment,
+ void *address
+);
+
+/*
+ * i386_Physical_to_logical
+ *
+ * Converts physical address to logical address.
+ */
+
+void *i386_Physical_to_logical(
+ unsigned short segment,
+ void *address
+);
+
+/*
+ * i386_Install_idt
+ *
+ * This routine installs an IDT entry.
+ */
+
+void i386_Install_idt(
+ unsigned int source_offset,
+ unsigned short destination_segment,
+ unsigned int destination_offset
+);
+
+/*
+ * "Simpler" names for a lot of the things defined in this file
+ */
+
+/* segment access routines */
+
+#define get_cs() i386_get_cs()
+#define get_ds() i386_get_ds()
+#define get_es() i386_get_es()
+#define get_ss() i386_get_ss()
+#define get_fs() i386_get_fs()
+#define get_gs() i386_get_gs()
+
+#define CPU_swap_u32( _value ) i386_swap_U32( _value )
+
+/* i80x86 I/O instructions */
+
+#define outport_byte( _port, _value ) i386_outport_byte( _port, _value )
+#define outport_word( _port, _value ) i386_outport_word( _port, _value )
+#define outport_long( _port, _value ) i386_outport_long( _port, _value )
+#define inport_byte( _port, _value ) i386_inport_byte( _port, _value )
+#define inport_word( _port, _value ) i386_inport_word( _port, _value )
+#define inport_long( _port, _value ) i386_inport_long( _port, _value )
+
+/* complicated static inline functions */
+
+#define get_GDTR( _gdtr_address ) \
+ i386_get_GDTR( _gdtr_address )
+
+#define get_GDT_slot( _gdtr_base, _segment, _slot_address ) \
+ i386_get_GDT_slot( _gdtr_base, _segment, _slot_address )
+
+#define set_GDT_slot( _gdtr_base, _segment, _slot_address ) \
+ i386_set_GDT_slot( _gdtr_base, _segment, _slot_address )
+
+#define set_segment( _segment, _base, _limit ) \
+ i386_set_segment( _segment, _base, _limit )
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/c/src/exec/score/cpu/i386/rtems.s b/c/src/exec/score/cpu/i386/rtems.s
new file mode 100644
index 0000000000..df65600e15
--- /dev/null
+++ b/c/src/exec/score/cpu/i386/rtems.s
@@ -0,0 +1,31 @@
+/* rtems.s
+ *
+ * This file contains the single entry point code for
+ * the i386 implementation of RTEMS.
+ *
+ * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
+ * On-Line Applications Research Corporation (OAR).
+ * All rights assigned to U.S. Government, 1994.
+ *
+ * This material may be reproduced by or for the U.S. Government pursuant
+ * to the copyright license under the clause at DFARS 252.227-7013. This
+ * notice must appear in all copies of this file and its derivatives.
+ *
+ * $Id$
+ */
+
+#include <asm.h>
+
+ EXTERN (_Entry_points)
+
+ BEGIN_CODE
+
+ .align 2
+ PUBLIC (RTEMS)
+
+SYM (RTEMS):
+ jmpl SYM (_Entry_points)(,eax,4)
+
+ END_CODE
+
+END