diff options
Diffstat (limited to 'c/src/exec/score/cpu/i386')
-rw-r--r-- | c/src/exec/score/cpu/i386/asm.h | 131 | ||||
-rw-r--r-- | c/src/exec/score/cpu/i386/cpu.c | 121 | ||||
-rw-r--r-- | c/src/exec/score/cpu/i386/cpu.h | 367 | ||||
-rw-r--r-- | c/src/exec/score/cpu/i386/cpu_asm.s | 654 | ||||
-rw-r--r-- | c/src/exec/score/cpu/i386/i386.h | 493 | ||||
-rw-r--r-- | c/src/exec/score/cpu/i386/rtems.s | 31 |
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 |