summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/i386
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/cpu/i386')
-rw-r--r--cpukit/score/cpu/i386/.cvsignore2
-rw-r--r--cpukit/score/cpu/i386/ChangeLog515
-rw-r--r--cpukit/score/cpu/i386/Makefile.am20
-rw-r--r--cpukit/score/cpu/i386/cpu.c244
-rw-r--r--cpukit/score/cpu/i386/cpu_asm.S320
-rw-r--r--cpukit/score/cpu/i386/preinstall.am53
-rw-r--r--cpukit/score/cpu/i386/rtems/asm.h139
-rw-r--r--cpukit/score/cpu/i386/rtems/score/cpu.h660
-rw-r--r--cpukit/score/cpu/i386/rtems/score/i386.h246
-rw-r--r--cpukit/score/cpu/i386/rtems/score/idtr.h66
-rw-r--r--cpukit/score/cpu/i386/rtems/score/interrupts.h79
-rw-r--r--cpukit/score/cpu/i386/rtems/score/registers.h72
-rw-r--r--cpukit/score/cpu/i386/rtems/score/types.h44
-rw-r--r--cpukit/score/cpu/i386/sse_test.c954
14 files changed, 3414 insertions, 0 deletions
diff --git a/cpukit/score/cpu/i386/.cvsignore b/cpukit/score/cpu/i386/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/i386/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/i386/ChangeLog b/cpukit/score/cpu/i386/ChangeLog
new file mode 100644
index 0000000000..4f78220d02
--- /dev/null
+++ b/cpukit/score/cpu/i386/ChangeLog
@@ -0,0 +1,515 @@
+2011-02-11 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * cpu.c, sse_test.c, rtems/score/cpu.h, rtems/score/i386.h,
+ rtems/score/interrupts.h:
+ Use "__asm__" instead of "asm" for improved c99-compliance.
+
+2010-07-29 Gedare Bloom <giddyup44@yahoo.com>
+
+ PR 1635/cpukit
+ * rtems/score/types.h: Refactoring of priority handling, to isolate the
+ bitmap implementation of priorities in the supercore so that priority
+ management is a little more modular. This change is in anticipation
+ of scheduler implementations that can select how they manage tracking
+ priority levels / finding the highest priority ready task. Note that
+ most of the changes here are simple renaming, to clarify the use of
+ the bitmap-based priority management.
+
+2010-07-16 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * rtems/score/cpu.h: Include <rtems/score/types.h> first.
+ * rtems/score/types.h: Use <rtems/score/basedefs.h> header file.
+
+2010-06-15 Joel Sherrill <joel.sherrill@oarcorp.com>
+
+ * cpu_asm.S: Formatting.
+
+2010-05-21 Vinu Rajashekhar <vinutheraj@gmail.com>
+
+ * rtems/score/registers.h: Remove structs with bit-fields. Add a mask
+ for cr3 page directory.
+
+2010-03-27 Joel Sherrill <joel.sherrill@oarcorp.com>
+
+ * cpu.c, cpu_asm.S, sse_test.c: Add include of config.h
+
+2009-11-09 Till Straumann <strauman@slac.stanford.edu>
+
+ PR 1469/cpukit
+ * cpu.c: Add dummy entry for (non-existing) exception #15.
+ Otherwise all slots for vectors >= 16 are one element off.
+
+2009-10-29 Till Straumann <strauman@slac.stanford.edu>
+
+ * rtems/score/cpu.h: Define _CPU_Interrupt_stack_setup() macro
+ which reserves space for the 'vector' arg to _C_dispatch_isr()
+ routine and aligns the irq stack to CPU_STACK_ALIGNMENT.
+
+2009-10-28 Till Straumann <strauman@slac.stanford.edu>
+
+ * rtems/score/cpu.h: Replaced misleading typedef of
+ CPU_Interrupt_frame by 'void'. The i386 port does not
+ pass any frame info to the interrupt handlers.
+
+2009-10-28 Till Straumann <strauman@slac.stanford.edu>
+
+ * rtems/score/cpu.h:
+ Added #ifdef ASM constructs so that this header can be
+ included from assembly code.
+
+ Increased CPU_STACK_ALIGNMENT to 16 bytes. Gcc maintains
+ 16-byte alignment and it may be a advantageous to provide
+ initial 16-byte alignment. When using SSE some gcc versions
+ may produce code that crashes if the stack is not 16-byte aligned.
+
+ Make sure _CPU_Context_Initialize() sets the thread stack
+ up so that it is aligned to CPU_CACHE_ALIGNMENT.
+
+ * cpu_asm.S:
+ Align stack to CPU_CACHE_ALIGNMENT before calling C-code.
+
+2009-10-27 Till Straumann <strauman@slac.stanford.edu>
+
+ * rtems/asm.h: Added definition for cr4 register.
+
+2009-09-25 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ * rtems/score/cpu.h: Add no return atrribute to _CPU_Context_restore()
+ since it is used for restarting self.
+
+2009-02-12 Joel Sherrill <joel.sherrill@oarcorp.com>
+
+ * cpu.c, rtems/score/cpu.h: Change prototype of IDLE thread to
+ consistently return void * and take a uintptr_t argument.
+
+2009-02-11 Joel Sherrill <joel.sherrill@oarcorp.com>
+
+ * cpu.c, rtems/score/cpu.h: Eliminate _CPU_Thread_dispatch_pointer and
+ passing address of _Thread_Dispatch to _CPU_Initialize. Clean up
+ comments.
+
+2008-09-11 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * rtems/score/types.h: Do not define boolean, single_precision,
+ double_precision unless RTEMS_DEPRECATED_TYPES is given.
+
+2008-09-08 Joel Sherrill <joel.sherrill@oarcorp.com>
+
+ * rtems/score/cpu.h: Remove extraneous spaces.
+
+2008-09-05 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * cpu.c: Stop using old-style defs.
+
+2008-08-21 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * rtems/score/types.h: Include stdbool.h.
+ Use bool as base-type for boolean.
+
+2008-08-19 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ * cpu.c: Fix prototypes.
+ * rtems/score/cpu.h: Use memcpy() initialize FP structure and avoid
+ many casts and potential warnings.
+
+2008-08-16 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * rtems/score/cpu.h, rtems/score/i386.h: Add missing prototypes.
+
+2008-07-31 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ * cpu.c, rtems/score/cpu.h: Correct prototype of Idle threads.
+
+2007-12-17 Joel Sherrill <joel.sherrill@oarcorp.com>
+
+ * rtems/score/cpu.h: Add _CPU_Context_Get_SP() for stack check utility.
+
+2007-12-17 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ * rtems/score/idtr.h: Sweep to make sure grep for COPYRIGHT passes.
+
+2007-12-04 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ * cpu.c, rtems/score/cpu.h: Move interrupt_stack_size field from CPU
+ Table to Configuration Table. Eliminate CPU Table from all ports.
+ Delete references to CPU Table in all forms.
+
+2007-12-03 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ * rtems/score/cpu.h: Moved most of the remaining CPU Table fields to
+ the Configuration Table. This included pretasking_hook,
+ predriver_hook, postdriver_hook, idle_task, do_zero_of_workspace,
+ extra_mpci_receive_server_stack, stack_allocate_hook, and
+ stack_free_hook. As a side-effect of this effort some multiprocessing
+ code was made conditional and some style clean up occurred.
+
+2007-11-26 Joel Sherrill <joel.sherrill@oarcorp.com>
+
+ * rtems/score/cpu.h: Eliminate the interrupt_table_segment and
+ interrupt_table_offset fields in the i386 CPU Table since they are
+ never read.
+
+2007-05-09 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * rtems/score/cpu.h: Remove CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES.
+
+2007-04-17 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * cpu.c:
+ Use Context_Control_fp* instead of void* for fp_contexts.
+ * rtems/score/cpu.h:
+ Use Context_Control_fp* instead of void* for fp_contexts.
+
+2006-11-17 Ralf Corsépius <ralf.corsepius@rtems.org>
+
+ * rtems/score/types.h: Remove unsigned64, signed64.
+
+2006-02-01 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Increase default stack size on i386 from 1K to 4K.
+ Most i386 targets are not memory strapped so making this a bit large
+ is not a burden. It lets more tests run. ticker and psxtimer will not
+ even run with 1K of stack.
+
+2005-11-08 Ralf Corsepius <ralf.corsepius@rtems.org>
+
+ * rtems/score/types.h: Eliminate unsigned16, unsigned32.
+
+2005-10-27 Ralf Corsepius <ralf.corsepius@rtems.org>
+
+ * rtems/asm.h: Remove private version of CONCAT macros.
+ Include <rtems/concat.h> instead.
+
+2005-02-08 Ralf Corsepius <ralf.corsepius@rtems.org>
+
+ * Makefile.am: Split out preinstallation rules.
+ * preinstall.am: New (Split out from Makefile.am).
+
+2005-02-04 Ralf Corsepius <ralf.corsepius@rtems.org>
+
+ PR 754/rtems
+ * rtems/asm.h: New (relocated from .).
+ * asm.h: Remove (moved to rtems/asm.h).
+ * Makefile.am: Reflect changes above.
+
+2004-01-28 Ralf Corsepius <ralf.corsepiu@rtems.org>
+
+ * asm.h, rtems/score/cpu.h, rtems/score/i386.h, rtems/score/idtr.h,
+ rtems/score/interrupts.h, rtems/score/registers.h,
+ rtems/score/types.h: New header guards.
+
+2005-01-24 Ralf Corsepius <ralf.corsepius@rtems.org>
+
+ * rtems/score/types.h: Remove signed8, signed16, signed32,
+ unsigned8, unsigned16, unsigned32.
+
+2005-01-24 Ralf Corsepius <ralf.corsepius@rtems.org>
+
+ * rtems/score/i386.h: *_swap_u32( uint32_t ).
+
+2005-01-24 Ralf Corsepius <ralf.corsepius@rtems.org>
+
+ * rtems/score/i386.h: *_swap_u16( uint16_t ).
+
+2005-01-24 Ralf Corsepius <ralf.corsepius@rtems.org>
+
+ * rtems/score/types.h: #include <rtems/stdint.h>.
+
+2005-01-07 Ralf Corsepius <ralf.corsepius@rtems.org>
+
+ * Makefile.am: Eliminate CFLAGS_OPTIMIZE_V.
+
+2005-01-01 Ralf Corsepius <ralf.corsepius@rtems.org>
+
+ * Makefile.am: Remove build-variant support.
+
+2004-11-21 Ralf Corsepius <ralf.corsepius@rtems.org>
+
+ * rtems/score/types.h: Use __rtems_score_types_h as preprocessor
+ guard.
+
+2004-11-21 Ralf Corsepius <ralf.corsepius@rtems.org>
+
+ * asm.h: Add doxygen preamble.
+
+2004-10-02 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * rtems/score/cpu.h: Add doxygen preamble.
+ * rtems/score/i386.h: Add doxygen preamble.
+ * rtems/score/idtr.h: Add doxygen preamble.
+ * rtems/score/interrupts.h: Add doxygen preamble.
+ * rtems/score/registers.h: Add doxygen preamble.
+ * rtems/score/types.h: Add doxygen preamble.
+
+2004-04-16 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * rtems/score/i386.h: Rename i386_swap_U* to i386_swap_u* (API
+ consistency with other ports).
+
+2004-04-09 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu_asm.S: Convert asm comments to C-comments to prevent gcc-3.4.0pre
+ from choking on them.
+
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Remove (Merged into $(top_srcdir)/configure.ac).
+ * Makefile.am: Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install asm.h to $(includedir)/rtems.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu_asm.S: Include <rtems/asm.h> instead of <asm.h>.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu.c, cpu_asm.S, rtems/score/cpu.h, rtems/score/interrupts.h:
+ Convert to using c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-02-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ PR 565/rtems
+ * asm.h: Various hacks.
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-12-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove TMPINSTALL_FILES.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, cpu_asm.S, rtems/score/cpu.h, rtems/score/i386.h,
+ rtems/score/idtr.h, rtems/score/interrupts.h,
+ rtems/score/registers.h, rtems/score/types.h: URL for license
+ changed.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use . instead of .o.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: RTEMS_TOP(../../../..).
+
+2002-07-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems.S: Remove.
+ * Makefile.am: Reflect changes above.
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add RTEMS_PROG_CCAS
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2002-03-29 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/idtr.h: New file, extracted from libcpu/cpu.h.
+ * rtems/score/interrupts.h: New file, extracted from libcpu/cpu.h.
+ * rtems/score/registers.h: New file, moved from libcpu.
+ * Makefile.am: Reflect changes above.
+ * cpu.c: Don't include cpuModel.h,
+ #include <rtems.h>,
+ #include <rtems/score/i386types.h>,
+ #include <rtems/score/idtr.h>.
+ * rtems/score/cpu.h: Don't include libcpu/cpu.h.
+ #include <rtems/score/interrupts.h>,
+ #include <rtems/score/registers.h>.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/i386types.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2001-02-05 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/Makefile.am, rtems/score/Makefile.am: Removed again.
+
+2002-01-31 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * configure.ac: Reflect changes above.
+ * Makefile.am: Reflect changes above.
+
+2001-01-30 Joel Sherrill <joel@OARcorp.com>
+
+ * Makefile.am: Corrected so .h files from rtems/score/ are installed.
+
+2002-01-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * cpu.c: Include rtems/bspIo.h instead of bspIo.h.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add multilib support.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use 'PREINSTALL_FILES ='.
+ * Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Added _CPU_Initialize_vectors().
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-09-12 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/i386.h: Corrected "#elsif" to be "#elif".
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am.
+
+2000-08-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/i386.h: cpu-variant define handling
+ Rewrite due to introduction of multilib defines.
+ * asm.h: include cpuopts.h instead of targopts.h
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
diff --git a/cpukit/score/cpu/i386/Makefile.am b/cpukit/score/cpu/i386/Makefile.am
new file mode 100644
index 0000000000..f6c8e7f6d7
--- /dev/null
+++ b/cpukit/score/cpu/i386/Makefile.am
@@ -0,0 +1,20 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS= rtems/asm.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/cpu.h rtems/score/i386.h \
+ rtems/score/types.h rtems/score/interrupts.h rtems/score/registers.h \
+ rtems/score/idtr.h
+
+noinst_LIBRARIES = libscorecpu.a
+libscorecpu_a_SOURCES = cpu.c cpu_asm.S
+libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS)
+
+include $(srcdir)/preinstall.am
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/i386/cpu.c b/cpukit/score/cpu/i386/cpu.c
new file mode 100644
index 0000000000..56971b63d5
--- /dev/null
+++ b/cpukit/score/cpu/i386/cpu.c
@@ -0,0 +1,244 @@
+/*
+ * Intel i386 Dependent Source
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/system.h>
+#include <rtems/score/types.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/idtr.h>
+
+#include <rtems/bspIo.h>
+#include <rtems/score/thread.h>
+
+/* _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * INPUT PARAMETERS: NONE
+ */
+
+void _CPU_Initialize(void)
+{
+#if CPU_HARDWARE_FP
+ register uint16_t fp_status __asm__ ("ax");
+ register Context_Control_fp *fp_context;
+#endif
+
+ /*
+ * 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 WAIT form of the coprocessor instructions
+ * MUST be used in case there is not a coprocessor
+ * to wait for.
+ */
+
+#if CPU_HARDWARE_FP
+ 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;
+
+#ifdef __SSE__
+ asm volatile( "fstcw %0":"=m"(fp_context->fpucw) );
+#else
+ __asm__ volatile( "fsave (%0)" : "=r" (fp_context)
+ : "0" (fp_context)
+ );
+#endif
+ }
+#endif
+
+#ifdef __SSE__
+
+ __asm__ volatile("stmxcsr %0":"=m"(fp_context->mxcsr));
+
+ /* The BSP must enable the SSE extensions (early).
+ * If any SSE instruction was already attempted
+ * then that crashed the system.
+ * As a courtesy, we double-check here but it
+ * may be too late (which is also why we don't
+ * enable SSE here).
+ */
+ {
+ uint32_t cr4;
+ __asm__ __volatile__("mov %%cr4, %0":"=r"(cr4));
+ if ( 0x600 != (cr4 & 0x600) ) {
+ printk("PANIC: RTEMS was compiled for SSE but BSP did not enable it (CR4: 0x%08x)\n", cr4);
+ while ( 1 ) {
+ __asm__ __volatile__("hlt");
+ }
+ }
+ }
+#endif
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Get_level
+ */
+
+uint32_t _CPU_ISR_Get_level( void )
+{
+ uint32_t level;
+
+ i386_get_interrupt_level( level );
+
+ return level;
+}
+
+void *_CPU_Thread_Idle_body( uintptr_t ignored )
+{
+ while(1){
+ __asm__ volatile ("hlt");
+ }
+ return NULL;
+}
+
+struct Frame_ {
+ struct Frame_ *up;
+ uintptr_t pc;
+};
+
+void _defaultExcHandler (CPU_Exception_frame *ctx)
+{
+ unsigned int faultAddr = 0;
+ printk("----------------------------------------------------------\n");
+ printk("Exception %d caught at PC %x by thread %d\n",
+ ctx->idtIndex,
+ ctx->eip,
+ _Thread_Executing->Object.id);
+ printk("----------------------------------------------------------\n");
+ printk("Processor execution context at time of the fault was :\n");
+ printk("----------------------------------------------------------\n");
+ printk(" EAX = %x EBX = %x ECX = %x EDX = %x\n",
+ ctx->eax, ctx->ebx, ctx->ecx, ctx->edx);
+ printk(" ESI = %x EDI = %x EBP = %x ESP = %x\n",
+ ctx->esi, ctx->edi, ctx->ebp, ctx->esp0);
+ printk("----------------------------------------------------------\n");
+ printk("Error code pushed by processor itself (if not 0) = %x\n",
+ ctx->faultCode);
+ printk("----------------------------------------------------------\n");
+ if (ctx->idtIndex == I386_EXCEPTION_PAGE_FAULT){
+ faultAddr = i386_get_cr2();
+ printk("Page fault linear address (CR2) = %x\n", faultAddr);
+ printk("----------------------------------------------------------\n\n");
+ }
+ if (_ISR_Nest_level > 0) {
+ /*
+ * In this case we shall not delete the task interrupted as
+ * it has nothing to do with the fault. We cannot return either
+ * because the eip points to the faulty instruction so...
+ */
+ printk("Exception while executing ISR!!!. System locked\n");
+ _CPU_Fatal_halt(faultAddr);
+ }
+ else {
+ struct Frame_ *fp = (struct Frame_*)ctx->ebp;
+ int i;
+
+ printk("Call Stack Trace of EIP:\n");
+ if ( fp ) {
+ for ( i=1; fp->up; fp=fp->up, i++ ) {
+ printk("0x%08x ",fp->pc);
+ if ( ! (i&3) )
+ printk("\n");
+ }
+ }
+ printk("\n");
+ /*
+ * OK I could probably use a simplified version but at least this
+ * should work.
+ */
+ printk(" ************ FAULTY THREAD WILL BE SUSPENDED **************\n");
+ rtems_task_suspend(_Thread_Executing->Object.id);
+ }
+}
+
+cpuExcHandlerType _currentExcHandler = _defaultExcHandler;
+
+extern void rtems_exception_prologue_0(void);
+extern void rtems_exception_prologue_1(void);
+extern void rtems_exception_prologue_2(void);
+extern void rtems_exception_prologue_3(void);
+extern void rtems_exception_prologue_4(void);
+extern void rtems_exception_prologue_5(void);
+extern void rtems_exception_prologue_6(void);
+extern void rtems_exception_prologue_7(void);
+extern void rtems_exception_prologue_8(void);
+extern void rtems_exception_prologue_9(void);
+extern void rtems_exception_prologue_10(void);
+extern void rtems_exception_prologue_11(void);
+extern void rtems_exception_prologue_12(void);
+extern void rtems_exception_prologue_13(void);
+extern void rtems_exception_prologue_14(void);
+extern void rtems_exception_prologue_16(void);
+extern void rtems_exception_prologue_17(void);
+extern void rtems_exception_prologue_18(void);
+#ifdef __SSE__
+extern void rtems_exception_prologue_19(void);
+#endif
+
+static rtems_raw_irq_hdl tbl[] = {
+ rtems_exception_prologue_0,
+ rtems_exception_prologue_1,
+ rtems_exception_prologue_2,
+ rtems_exception_prologue_3,
+ rtems_exception_prologue_4,
+ rtems_exception_prologue_5,
+ rtems_exception_prologue_6,
+ rtems_exception_prologue_7,
+ rtems_exception_prologue_8,
+ rtems_exception_prologue_9,
+ rtems_exception_prologue_10,
+ rtems_exception_prologue_11,
+ rtems_exception_prologue_12,
+ rtems_exception_prologue_13,
+ rtems_exception_prologue_14,
+ 0,
+ rtems_exception_prologue_16,
+ rtems_exception_prologue_17,
+ rtems_exception_prologue_18,
+#ifdef __SSE__
+ rtems_exception_prologue_19,
+#endif
+};
+
+void rtems_exception_init_mngt(void)
+{
+ size_t i,j;
+ interrupt_gate_descriptor *currentIdtEntry;
+ unsigned limit;
+ unsigned level;
+
+ i = sizeof(tbl) / sizeof (rtems_raw_irq_hdl);
+
+ i386_get_info_from_IDTR (&currentIdtEntry, &limit);
+
+ _CPU_ISR_Disable(level);
+ for (j = 0; j < i; j++) {
+ create_interrupt_gate_descriptor (&currentIdtEntry[j], tbl[j]);
+ }
+ _CPU_ISR_Enable(level);
+}
diff --git a/cpukit/score/cpu/i386/cpu_asm.S b/cpukit/score/cpu/i386/cpu_asm.S
new file mode 100644
index 0000000000..418d2bf787
--- /dev/null
+++ b/cpukit/score/cpu/i386/cpu_asm.S
@@ -0,0 +1,320 @@
+/* cpu_asm.s
+ *
+ * This file contains all assembly code for the Intel i386 implementation
+ * of RTEMS.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/asm.h>
+#include <rtems/score/cpu.h>
+
+#ifndef CPU_STACK_ALIGNMENT
+#error "Missing header? CPU_STACK_ALIGNMENT not defined"
+#endif
+
+/*
+ * 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.
+ */
+
+ .p2align 1
+ 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 */
+
+#ifndef __SSE__
+ .p2align 1
+ 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
+
+ .p2align 1
+ 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
+#endif
+
+#ifdef __SSE__
+#define SSE_OFF 16
+#endif
+
+ PUBLIC (_Exception_Handler)
+SYM (_Exception_Handler):
+ pusha /* Push general purpose registers */
+ pushl $0 /* Null pointer to SSE area */
+ movl esp, ebp /* Save original SP */
+#ifndef __SSE__
+ subl $4, esp /* Reserve space for argument */
+ /* Align stack (courtesy for C/gcc) */
+ andl $ - CPU_STACK_ALIGNMENT, esp
+#else
+ subl $512, esp /* Space for SSE area */
+ /* Align stack (courtesy for C/gcc) */
+ andl $ - CPU_STACK_ALIGNMENT, esp
+/* Doing fwait here will re-throw an already pending FP exception!
+ fwait
+ */
+ fxsave 0(esp)
+ fninit /* Clean-slate FPU */
+ movl $0x1f80, 0(ebp)
+ ldmxcsr 0(ebp) /* Clean-slate MXCSR */
+ movl esp, 0(ebp) /* Store pointer to SSE area */
+ subl $SSE_OFF, esp /* Aligned space for argument */
+#endif
+ movl ebp, (esp) /* Store argument */
+ movl _currentExcHandler, eax /* Call function stored in _currentExcHandler */
+ call * eax
+#ifdef __SSE__
+ fwait
+ fxrstor 16(esp)
+#endif
+ movl ebp, esp /* Restore original SP */
+ addl $4, esp /* Skill pointer to SSE area */
+ popa /* Restore general purpose registers */
+ addl $8, esp /* Skill vector number and faultCode */
+ iret
+
+#define DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY(_vector) \
+ .p2align 4 ; \
+ PUBLIC (rtems_exception_prologue_ ## _vector ) ; \
+SYM (rtems_exception_prologue_ ## _vector ): \
+ pushl $ _vector ; \
+ jmp SYM (_Exception_Handler) ;
+
+#define DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY(_vector) \
+ .p2align 4 ; \
+ PUBLIC (rtems_exception_prologue_ ## _vector ) ; \
+SYM (rtems_exception_prologue_ ## _vector ): \
+ pushl $ 0 ; \
+ pushl $ _vector ; \
+ jmp SYM (_Exception_Handler) ;
+
+/*
+ * Divide Error
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (0)
+/*
+ * Debug Exception
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (1)
+/*
+ * NMI
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (2)
+/*
+ * Breakpoint
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (3)
+/*
+ * Overflow
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (4)
+/*
+ * Bound Range Exceeded
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (5)
+/*
+ * Invalid Opcode
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (6)
+/*
+ * No Math Coproc
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (7)
+/*
+ * Double Fault
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (8)
+/*
+ * Coprocessor segment overrun
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (9)
+/*
+ * Invalid TSS
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (10)
+/*
+ * Segment Not Present
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (11)
+/*
+ * Stack segment Fault
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (12)
+/*
+ * General Protection Fault
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (13)
+/*
+ * Page Fault
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (14)
+/*
+ * Floating point error (NB 15 is reserved it is therefor skipped)
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (16)
+/*
+ * Aligment Check
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (17)
+/*
+ * Machine Check
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (18)
+
+#ifdef __SSE__
+/*
+ * SIMD FP Exception
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (19)
+#endif
+
+
+/*
+ * void *i386_Logical_to_physical(
+ * uint16_t 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(
+ * uint16_t 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/cpukit/score/cpu/i386/preinstall.am b/cpukit/score/cpu/i386/preinstall.am
new file mode 100644
index 0000000000..7bf7af259a
--- /dev/null
+++ b/cpukit/score/cpu/i386/preinstall.am
@@ -0,0 +1,53 @@
+## Automatically generated by ampolish3 - Do not edit
+
+if AMPOLISH3
+$(srcdir)/preinstall.am: Makefile.am
+ $(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am
+endif
+
+PREINSTALL_DIRS =
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+all-am: $(PREINSTALL_FILES)
+
+PREINSTALL_FILES =
+CLEANFILES = $(PREINSTALL_FILES)
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(MKDIR_P) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: rtems/asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(MKDIR_P) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/i386.h: rtems/score/i386.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/i386.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/i386.h
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+$(PROJECT_INCLUDE)/rtems/score/interrupts.h: rtems/score/interrupts.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/interrupts.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/interrupts.h
+
+$(PROJECT_INCLUDE)/rtems/score/registers.h: rtems/score/registers.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/registers.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/registers.h
+
+$(PROJECT_INCLUDE)/rtems/score/idtr.h: rtems/score/idtr.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/idtr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/idtr.h
+
diff --git a/cpukit/score/cpu/i386/rtems/asm.h b/cpukit/score/cpu/i386/rtems/asm.h
new file mode 100644
index 0000000000..f18d54c5b1
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/asm.h
@@ -0,0 +1,139 @@
+/**
+ * @file rtems/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-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef _RTEMS_ASM_H
+#define _RTEMS_ASM_H
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/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
+*/
+
+#include <rtems/concat.h>
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT0 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT0 (__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 cr0 REG (cr0)
+#define cr4 REG (cr4)
+
+#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 bh REG (bh)
+#define ch REG (ch)
+#define dh REG (dh)
+
+#define al REG (al)
+#define bl REG (bl)
+#define cl REG (cl)
+#define dl REG (dl)
+
+#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 .data
+#define END_DATA
+#define BEGIN_BSS .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
diff --git a/cpukit/score/cpu/i386/rtems/score/cpu.h b/cpukit/score/cpu/i386/rtems/score/cpu.h
new file mode 100644
index 0000000000..0e47c285bb
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/score/cpu.h
@@ -0,0 +1,660 @@
+/**
+ * @file rtems/score/cpu.h
+ */
+
+/*
+ * This include file contains information pertaining to the Intel
+ * i386 processor.
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _RTEMS_SCORE_CPU_H
+#define _RTEMS_SCORE_CPU_H
+
+#ifndef ASM
+#include <string.h> /* for memcpy */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/types.h>
+#include <rtems/score/i386.h>
+
+#ifndef ASM
+#include <rtems/score/interrupts.h> /* formerly in libcpu/cpu.h> */
+#include <rtems/score/registers.h> /* formerly part of libcpu */
+#endif
+
+/* 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
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 0
+
+/*
+ * Some family members have no FP, some have an FPU such as the i387
+ * for the i386, others have it built in (i486DX, Pentium).
+ */
+
+#ifdef __SSE__
+#define CPU_HARDWARE_FP TRUE
+#define CPU_SOFTWARE_FP FALSE
+
+#define CPU_ALL_TASKS_ARE_FP TRUE
+#define CPU_IDLE_TASK_IS_FP TRUE
+#define CPU_USE_DEFERRED_FP_SWITCH FALSE
+#else /* __SSE__ */
+
+#if ( I386_HAS_FPU == 1 )
+#define CPU_HARDWARE_FP TRUE /* i387 for i386 */
+#else
+#define CPU_HARDWARE_FP FALSE
+#endif
+#define CPU_SOFTWARE_FP FALSE
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+#define CPU_IDLE_TASK_IS_FP FALSE
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+#endif /* __SSE__ */
+
+#define CPU_STACK_GROWS_UP FALSE
+#define CPU_STRUCTURE_ALIGNMENT
+
+/*
+ * Does this port provide a CPU dependent IDLE task implementation?
+ *
+ * If TRUE, then the routine _CPU_Thread_Idle_body
+ * must be provided and is the default IDLE thread body instead of
+ * _CPU_Thread_Idle_body.
+ *
+ * If FALSE, then use the generic IDLE thread body if the BSP does
+ * not provide one.
+ */
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY TRUE
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ */
+
+#define CPU_BIG_ENDIAN FALSE
+#define CPU_LITTLE_ENDIAN TRUE
+
+/* structures */
+
+#ifndef ASM
+
+/*
+ * Basic integer context for the i386 family.
+ */
+
+typedef struct {
+ uint32_t eflags; /* extended flags register */
+ void *esp; /* extended stack pointer register */
+ void *ebp; /* extended base pointer register */
+ uint32_t ebx; /* extended bx register */
+ uint32_t esi; /* extended source index register */
+ uint32_t edi; /* extended destination index flags register */
+} Context_Control;
+
+#define _CPU_Context_Get_SP( _context ) \
+ (_context)->esp
+
+/*
+ * FP context save area for the i387 numeric coprocessors.
+ */
+#ifdef __SSE__
+/* All FPU and SSE registers are volatile; hence, as long
+ * as we are within normally executing C code (including
+ * a task switch) there is no need for saving/restoring
+ * any of those registers.
+ * We must save/restore the full FPU/SSE context across
+ * interrupts and exceptions, however:
+ * - after ISR execution a _Thread_Dispatch() may happen
+ * and it is therefore necessary to save the FPU/SSE
+ * registers to be restored when control is returned
+ * to the interrupted task.
+ * - gcc may implicitly use FPU/SSE instructions in
+ * an ISR.
+ *
+ * Even though there is no explicit mentioning of the FPU
+ * control word in the SYSV ABI (i386) being non-volatile
+ * we maintain MXCSR and the FPU control-word for each task.
+ */
+typedef struct {
+ uint32_t mxcsr;
+ uint16_t fpucw;
+} Context_Control_fp;
+
+#else
+
+typedef struct {
+ uint8_t fp_save_area[108]; /* context size area for I80387 */
+ /* 28 bytes for environment */
+} Context_Control_fp;
+
+#endif
+
+
+/*
+ * The following structure defines the set of information saved
+ * on the current stack by RTEMS upon receipt of execptions.
+ *
+ * idtIndex is either the interrupt number or the trap/exception number.
+ * faultCode is the code pushed by the processor on some exceptions.
+ *
+ * Since the first registers are directly pushed by the CPU they
+ * may not respect 16-byte stack alignment, which is, however,
+ * mandatory for the SSE register area.
+ * Therefore, these registers are stored at an aligned address
+ * and a pointer is stored in the CPU_Exception_frame.
+ * If the executive was compiled without SSE support then
+ * this pointer is NULL.
+ */
+
+struct Context_Control_sse;
+
+typedef struct {
+ struct Context_Control_sse *fp_ctxt;
+ uint32_t edi;
+ uint32_t esi;
+ uint32_t ebp;
+ uint32_t esp0;
+ uint32_t ebx;
+ uint32_t edx;
+ uint32_t ecx;
+ uint32_t eax;
+ uint32_t idtIndex;
+ uint32_t faultCode;
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t eflags;
+} CPU_Exception_frame;
+
+#ifdef __SSE__
+typedef struct Context_Control_sse {
+ uint16_t fcw;
+ uint16_t fsw;
+ uint8_t ftw;
+ uint8_t res_1;
+ uint16_t fop;
+ uint32_t fpu_ip;
+ uint16_t cs;
+ uint16_t res_2;
+ uint32_t fpu_dp;
+ uint16_t ds;
+ uint16_t res_3;
+ uint32_t mxcsr;
+ uint32_t mxcsr_mask;
+ struct {
+ uint8_t fpreg[10];
+ uint8_t res_4[ 6];
+ } fp_mmregs[8];
+ uint8_t xmmregs[8][16];
+ uint8_t res_5[224];
+} Context_Control_sse
+__attribute__((aligned(16)))
+;
+#endif
+
+typedef void (*cpuExcHandlerType) (CPU_Exception_frame*);
+extern cpuExcHandlerType _currentExcHandler;
+extern void rtems_exception_init_mngt(void);
+
+/*
+ * This port does not pass any frame info to the
+ * interrupt handler.
+ */
+
+typedef void CPU_Interrupt_frame;
+
+typedef enum {
+ I386_EXCEPTION_DIVIDE_BY_ZERO = 0,
+ I386_EXCEPTION_DEBUG = 1,
+ I386_EXCEPTION_NMI = 2,
+ I386_EXCEPTION_BREAKPOINT = 3,
+ I386_EXCEPTION_OVERFLOW = 4,
+ I386_EXCEPTION_BOUND = 5,
+ I386_EXCEPTION_ILLEGAL_INSTR = 6,
+ I386_EXCEPTION_MATH_COPROC_UNAVAIL = 7,
+ I386_EXCEPTION_DOUBLE_FAULT = 8,
+ I386_EXCEPTION_I386_COPROC_SEG_ERR = 9,
+ I386_EXCEPTION_INVALID_TSS = 10,
+ I386_EXCEPTION_SEGMENT_NOT_PRESENT = 11,
+ I386_EXCEPTION_STACK_SEGMENT_FAULT = 12,
+ I386_EXCEPTION_GENERAL_PROT_ERR = 13,
+ I386_EXCEPTION_PAGE_FAULT = 14,
+ I386_EXCEPTION_INTEL_RES15 = 15,
+ I386_EXCEPTION_FLOAT_ERROR = 16,
+ I386_EXCEPTION_ALIGN_CHECK = 17,
+ I386_EXCEPTION_MACHINE_CHECK = 18,
+ I386_EXCEPTION_ENTER_RDBG = 50 /* to enter manually RDBG */
+
+} Intel_symbolic_exception_name;
+
+
+/*
+ * 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 */
+
+SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context;
+
+#endif /* ASM */
+
+/* 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 the MPCI receive server thread
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 1024
+
+/*
+ * i386 family supports 256 distinct vectors.
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
+
+/*
+ * This is defined if the port has a special way to report the ISR nesting
+ * level. Most ports maintain the variable _ISR_Nest_level.
+ */
+
+#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
+
+/*
+ * Minimum size of a thread's stack.
+ */
+
+#define CPU_STACK_MINIMUM_SIZE 4096
+
+/*
+ * 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. However, since gcc maintains 16-byte alignment
+ * we try to respect that. If you find an option to let gcc squeeze
+ * the stack more tightly then setting CPU_STACK_ALIGNMENT to 16 still
+ * doesn't waste much space since this only determines the *initial*
+ * alignment.
+ */
+
+#define CPU_STACK_ALIGNMENT 16
+
+/* macros */
+
+#ifndef ASM
+/*
+ * ISR handler macros
+ *
+ * These macros perform the following functions:
+ * + initialize the RTEMS vector table
+ * + disable all maskable CPU interrupts
+ * + restore previous interrupt level (enable)
+ * + temporarily restore interrupts (flash)
+ * + set a particular level
+ */
+
+#define _CPU_Initialize_vectors()
+
+#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" ); \
+ }
+
+uint32_t _CPU_ISR_Get_level( void );
+
+/* Make sure interrupt stack has space for ISR
+ * 'vector' arg at the top and that it is aligned
+ * properly.
+ */
+
+#define _CPU_Interrupt_stack_setup( _lo, _hi ) \
+ do { \
+ _hi = (void*)(((uintptr_t)(_hi) - 4) & ~ (CPU_STACK_ALIGNMENT - 1)); \
+ } while (0)
+
+#endif /* ASM */
+
+/* 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
+
+#ifndef ASM
+
+/*
+ * Stack alignment note:
+ *
+ * We want the stack to look to the '_entry_point' routine
+ * like an ordinary stack frame as if '_entry_point' was
+ * called from C-code.
+ * Note that '_entry_point' is jumped-to by the 'ret'
+ * instruction returning from _CPU_Context_switch() or
+ * _CPU_Context_restore() thus popping the _entry_point
+ * from the stack.
+ * However, _entry_point expects a frame to look like this:
+ *
+ * args [_Thread_Handler expects no args, however]
+ * ------ (alignment boundary)
+ * SP-> return_addr return here when _entry_point returns which (never happens)
+ *
+ *
+ * Hence we must initialize the stack as follows
+ *
+ * [arg1 ]: n/a
+ * [arg0 (aligned)]: n/a
+ * [ret. addr ]: NULL
+ * SP-> [jump-target ]: _entry_point
+ *
+ * When Context_switch returns it pops the _entry_point from
+ * the stack which then finds a standard layout.
+ */
+
+
+#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
+ _isr, _entry_point, _is_fp ) \
+ do { \
+ uint32_t _stack; \
+ \
+ if ( (_isr) ) (_the_context)->eflags = CPU_EFLAGS_INTERRUPTS_OFF; \
+ else (_the_context)->eflags = CPU_EFLAGS_INTERRUPTS_ON; \
+ \
+ _stack = ((uint32_t)(_stack_base)) + (_size); \
+ _stack &= ~ (CPU_STACK_ALIGNMENT - 1); \
+ _stack -= 2*sizeof(proc_ptr*); /* see above for why we need to do this */ \
+ *((proc_ptr *)(_stack)) = (_entry_point); \
+ (_the_context)->ebp = (void *) 0; \
+ (_the_context)->esp = (void *) _stack; \
+ } while (0)
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+#if defined(RTEMS_SMP)
+ #define _CPU_Context_switch_to_first_task_smp( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+ /* address space 1 is uncacheable */
+ #define SMP_CPU_SWAP( _address, _value, _previous ) \
+ do { \
+ asm volatile("lock; xchgl %0, %1" : \
+ "+m" (*_address), "=a" (_previous) : \
+ "1" (_value) : \
+ "cc"); \
+ } while (0)
+#endif
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
+
+#define _CPU_Context_Initialize_fp( _fp_area ) \
+ { \
+ memcpy( *_fp_area, &_CPU_Null_fp_context, CPU_CONTEXT_FP_SIZE ); \
+ }
+
+/* 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)) \
+ ); \
+ }
+
+#endif /* ASM */
+
+/* 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_USE_GENERIC_BITFIELD_CODE FALSE
+#define CPU_USE_GENERIC_BITFIELD_DATA FALSE
+
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { \
+ register uint16_t __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 */
+
+#ifndef ASM
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ */
+
+void _CPU_Initialize(void);
+
+/*
+ * _CPU_ISR_install_raw_handler
+ *
+ * This routine installs a "raw" interrupt handler directly into the
+ * processor's vector table.
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Thread_Idle_body
+ *
+ * Use the halt instruction of low power mode of a particular i386 model.
+ */
+
+#if (CPU_PROVIDES_IDLE_THREAD_BODY == TRUE)
+
+void *_CPU_Thread_Idle_body( uintptr_t ignored );
+
+#endif /* CPU_PROVIDES_IDLE_THREAD_BODY */
+
+/*
+ * _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 generally used only to restart self in an
+ * efficient manner and avoid stack conflicts.
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ */
+
+#ifdef __SSE__
+#define _CPU_Context_save_fp(fp_context_pp) \
+ do { \
+ __asm__ __volatile__( \
+ "fstcw %0" \
+ :"=m"((*(fp_context_pp))->fpucw) \
+ ); \
+ __asm__ __volatile__( \
+ "stmxcsr %0" \
+ :"=m"((*(fp_context_pp))->mxcsr) \
+ ); \
+ } while (0)
+#else
+void _CPU_Context_save_fp(
+ Context_Control_fp **fp_context_ptr
+);
+#endif
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ */
+#ifdef __SSE__
+#define _CPU_Context_restore_fp(fp_context_pp) \
+ do { \
+ __asm__ __volatile__( \
+ "fldcw %0" \
+ ::"m"((*(fp_context_pp))->fpucw) \
+ :"fpcr" \
+ ); \
+ __builtin_ia32_ldmxcsr(_Thread_Executing->fp_context->mxcsr); \
+ } while (0)
+#else
+void _CPU_Context_restore_fp(
+ Context_Control_fp **fp_context_ptr
+);
+#endif
+
+#ifdef __SSE__
+#define _CPU_Context_Initialization_at_thread_begin() \
+ do { \
+ __asm__ __volatile__( \
+ "finit" \
+ : \
+ : \
+ :"st","st(1)","st(2)","st(3)", \
+ "st(4)","st(5)","st(6)","st(7)", \
+ "fpsr","fpcr" \
+ ); \
+ if ( _Thread_Executing->fp_context ) { \
+ _CPU_Context_restore_fp(&_Thread_Executing->fp_context); \
+ } \
+ } while (0)
+#endif
+
+#endif /* ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/i386/rtems/score/i386.h b/cpukit/score/cpu/i386/rtems/score/i386.h
new file mode 100644
index 0000000000..2d8a8969cb
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/score/i386.h
@@ -0,0 +1,246 @@
+/**
+ * @file rtems/score/i386.h
+ */
+
+/*
+ * This include file contains information pertaining to the Intel
+ * i386 processor.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _RTEMS_SCORE_I386_H
+#define _RTEMS_SCORE_I386_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * 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_nofp (i386 DX or SX w/o i387)
+ * i486dx
+ * i486sx
+ * pentium
+ * pentiumpro
+ *
+ * CPU Model Feature Flags:
+ *
+ * I386_HAS_BSWAP: Defined to "1" if the instruction for endian swapping
+ * (bswap) should be used. This instruction appears to
+ * be present in all i486's and above.
+ *
+ * I386_HAS_FPU: Defined to "1" if the CPU has an FPU.
+ *
+ */
+
+#if defined(_SOFT_FLOAT)
+#define I386_HAS_FPU 0
+#else
+#define I386_HAS_FPU 1
+#endif
+
+#if defined(__pentiumpro__)
+
+#define CPU_MODEL_NAME "Pentium Pro"
+
+#elif defined(__i586__)
+
+# if defined(__pentium__)
+# define CPU_MODEL_NAME "Pentium"
+# elif defined(__k6__)
+# define CPU_MODEL_NAME "K6"
+# else
+# define CPU_MODEL_NAME "i586"
+# endif
+
+#elif defined(__i486__)
+
+# if !defined(_SOFT_FLOAT)
+# define CPU_MODEL_NAME "i486dx"
+# else
+# define CPU_MODEL_NAME "i486sx"
+# endif
+
+#elif defined(__i386__)
+
+#define I386_HAS_BSWAP 0
+
+# if !defined(_SOFT_FLOAT)
+# define CPU_MODEL_NAME "i386 with i387"
+# else
+# define CPU_MODEL_NAME "i386 w/o i387"
+# endif
+
+#else
+#error "Unknown CPU Model"
+#endif
+
+/*
+ * Set default values for CPU model feature flags
+ *
+ * NOTE: These settings are chosen to reflect most of the family members.
+ */
+
+#ifndef I386_HAS_FPU
+#define I386_HAS_FPU 1
+#endif
+
+#ifndef I386_HAS_BSWAP
+#define I386_HAS_BSWAP 1
+#endif
+
+/*
+ * Define the name of the CPU family.
+ */
+
+#define CPU_NAME "Intel i386"
+
+#ifndef ASM
+
+/*
+ * The following routine swaps the endian format of an unsigned int.
+ * It must be static so it can be referenced indirectly.
+ */
+
+static inline uint32_t i386_swap_u32(
+ uint32_t value
+)
+{
+ uint32_t lout;
+
+#if (I386_HAS_BSWAP == 0)
+ __asm__ volatile( "rorw $8,%%ax;"
+ "rorl $16,%0;"
+ "rorw $8,%%ax" : "=a" (lout) : "0" (value) );
+#else
+ __asm__ volatile( "bswap %0" : "=r" (lout) : "0" (value));
+#endif
+ return( lout );
+}
+
+static inline uint16_t i386_swap_u16(
+ uint16_t value
+)
+{
+ unsigned short sout;
+
+ __asm__ volatile( "rorw $8,%0" : "=r" (sout) : "0" (value));
+ return (sout);
+}
+
+
+/*
+ * Added for pagination management
+ */
+
+static inline unsigned int i386_get_cr0(void)
+{
+ register unsigned int segment = 0;
+
+ __asm__ volatile ( "movl %%cr0,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline void i386_set_cr0(unsigned int segment)
+{
+ __asm__ volatile ( "movl %0,%%cr0" : "=r" (segment) : "0" (segment) );
+}
+
+static inline unsigned int i386_get_cr2(void)
+{
+ register unsigned int segment = 0;
+
+ __asm__ volatile ( "movl %%cr2,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline unsigned int i386_get_cr3(void)
+{
+ register unsigned int segment = 0;
+
+ __asm__ volatile ( "movl %%cr3,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline void i386_set_cr3(unsigned int segment)
+{
+ __asm__ volatile ( "movl %0,%%cr3" : "=r" (segment) : "0" (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
+);
+
+
+/*
+ * "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 )
+#define CPU_swap_u16( _value ) i386_swap_u16( _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 )
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
diff --git a/cpukit/score/cpu/i386/rtems/score/idtr.h b/cpukit/score/cpu/i386/rtems/score/idtr.h
new file mode 100644
index 0000000000..361c8472b9
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/score/idtr.h
@@ -0,0 +1,66 @@
+/**
+ * @file rtems/score/idtr.h
+ */
+
+/*
+ * This file contains definitions for data structure related
+ * to Intel system programming. More information can be found
+ * on Intel site and more precisely in the following book :
+ *
+ * Pentium Processor familly
+ * Developper's Manual
+ *
+ * Volume 3 : Architecture and Programming Manual
+ *
+ * Formerly contained in and extracted from libcpu/i386/cpu.h.
+ *
+ * COPYRIGHT (C) 1998 Eric Valette (valette@crf.canon.fr)
+ * Canon Centre Recherche France.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Applications must not include this file directly.
+ */
+
+#ifndef _RTEMS_SCORE_IDTR_H
+#define _RTEMS_SCORE_IDTR_H
+
+/*
+ * See page 14.9 Figure 14-2.
+ *
+ */
+typedef struct
+{
+ unsigned int low_offsets_bits:16;
+ unsigned int segment_selector:16;
+ unsigned int fixed_value_bits:8;
+ unsigned int gate_type:5;
+ unsigned int privilege:2;
+ unsigned int present:1;
+ unsigned int high_offsets_bits:16;
+} interrupt_gate_descriptor;
+
+/*
+ * C callable function enabling to create a interrupt_gate_descriptor
+ */
+extern void create_interrupt_gate_descriptor (interrupt_gate_descriptor*, rtems_raw_irq_hdl);
+
+/*
+ * C callable function enabling to get easily usable info from
+ * the actual value of IDT register.
+ */
+extern void i386_get_info_from_IDTR (interrupt_gate_descriptor** table,
+ unsigned* limit);
+
+/*
+ * C callable function enabling to change the value of IDT register. Must be called
+ * with interrupts masked at processor level!!!.
+ */
+extern void i386_set_IDTR (interrupt_gate_descriptor* table,
+ unsigned limit);
+
+#endif
diff --git a/cpukit/score/cpu/i386/rtems/score/interrupts.h b/cpukit/score/cpu/i386/rtems/score/interrupts.h
new file mode 100644
index 0000000000..b6b541fb0e
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/score/interrupts.h
@@ -0,0 +1,79 @@
+/**
+ * @file rtems/score/interrupts.h
+ */
+
+/*
+ * i386 interrupt macros.
+ *
+ * Formerly contained in and extracted from libcpu/i386/cpu.h
+ *
+ * COPYRIGHT (c) 1998 valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Applications must not include this file directly.
+ */
+
+#ifndef _RTEMS_SCORE_INTERRUPTS_H
+#define _RTEMS_SCORE_INTERRUPTS_H
+
+#ifndef ASM
+
+struct __rtems_raw_irq_connect_data__;
+
+typedef void (*rtems_raw_irq_hdl) (void);
+typedef void (*rtems_raw_irq_enable) (const struct __rtems_raw_irq_connect_data__*);
+typedef void (*rtems_raw_irq_disable) (const struct __rtems_raw_irq_connect_data__*);
+typedef int (*rtems_raw_irq_is_enabled) (const struct __rtems_raw_irq_connect_data__*);
+
+/*
+ * Interrupt Level Macros
+ */
+
+#define i386_disable_interrupts( _level ) \
+ { \
+ __asm__ volatile ( "pushf ; \
+ cli ; \
+ pop %0" \
+ : "=rm" ((_level)) \
+ ); \
+ }
+
+#define i386_enable_interrupts( _level ) \
+ { \
+ __asm__ volatile ( "push %0 ; \
+ popf" \
+ : : "rm" ((_level)) : "cc" \
+ ); \
+ }
+
+#define i386_flash_interrupts( _level ) \
+ { \
+ __asm__ volatile ( "push %0 ; \
+ popf ; \
+ cli" \
+ : : "rm" ((_level)) : "cc" \
+ ); \
+ }
+
+#define i386_get_interrupt_level( _level ) \
+ do { \
+ register uint32_t _eflags; \
+ \
+ __asm__ volatile ( "pushf ; \
+ pop %0" \
+ : "=rm" ((_eflags)) \
+ ); \
+ \
+ _level = (_eflags & EFLAGS_INTR_ENABLE) ? 0 : 1; \
+ } while (0)
+
+#define _CPU_ISR_Disable( _level ) i386_disable_interrupts( _level )
+#define _CPU_ISR_Enable( _level ) i386_enable_interrupts( _level )
+
+#endif
+#endif
diff --git a/cpukit/score/cpu/i386/rtems/score/registers.h b/cpukit/score/cpu/i386/rtems/score/registers.h
new file mode 100644
index 0000000000..81c2a65e15
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/score/registers.h
@@ -0,0 +1,72 @@
+/**
+ * @file rtems/score/registers.h
+ */
+
+/*
+ * This file contains definition and constants related to Intel Cpu
+ *
+ * COPYRIGHT (c) 1998 valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _RTEMS_SCORE_REGISTERS_H
+#define _RTEMS_SCORE_REGISTERS_H
+
+/*
+ * definition related to EFLAGS
+ */
+#define EFLAGS_CARRY 0x1
+#define EFLAGS_PARITY 0x4
+
+#define EFLAGS_AUX_CARRY 0x10
+#define EFLAGS_ZERO 0x40
+#define EFLAGS_SIGN 0x80
+
+#define EFLAGS_TRAP 0x100
+#define EFLAGS_INTR_ENABLE 0x200
+#define EFLAGS_DIRECTION 0x400
+#define EFLAGS_OVERFLOW 0x800
+
+#define EFLAGS_IOPL_MASK 0x3000
+#define EFLAGS_NESTED_TASK 0x8000
+
+#define EFLAGS_RESUME 0x10000
+#define EFLAGS_VIRTUAL_MODE 0x20000
+#define EFLAGS_ALIGN_CHECK 0x40000
+#define EFLAGS_VIRTUAL_INTR 0x80000
+
+#define EFLAGS_VIRTUAL_INTR_PEND 0x100000
+#define EFLAGS_ID 0x200000
+
+/*
+ * definitions related to CR0
+ */
+#define CR0_PROTECTION_ENABLE 0x1
+#define CR0_MONITOR_COPROC 0x2
+#define CR0_COPROC_SOFT_EMUL 0x4
+#define CR0_FLOATING_INSTR_EXCEPTION 0x8
+
+#define CR0_EXTENSION_TYPE 0x10
+#define CR0_NUMERIC_ERROR 0x20
+
+#define CR0_WRITE_PROTECT 0x10000
+#define CR0_ALIGMENT_MASK 0x40000
+
+#define CR0_NO_WRITE_THROUGH 0x20000000
+#define CR0_PAGE_LEVEL_CACHE_DISABLE 0x40000000
+#define CR0_PAGING 0x80000000
+
+/*
+ * definitions related to CR3
+ */
+
+#define CR3_PAGE_CACHE_DISABLE 0x10
+#define CR3_PAGE_WRITE_THROUGH 0x8
+#define CR3_PAGE_DIRECTORY_MASK 0xFFFFF000
+
+#endif
diff --git a/cpukit/score/cpu/i386/rtems/score/types.h b/cpukit/score/cpu/i386/rtems/score/types.h
new file mode 100644
index 0000000000..3a21714a0a
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/score/types.h
@@ -0,0 +1,44 @@
+/**
+ * @file rtems/score/types.h
+ */
+
+/*
+ * This include file contains type definitions pertaining to the Intel
+ * i386 processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _RTEMS_SCORE_TYPES_H
+#define _RTEMS_SCORE_TYPES_H
+
+#include <rtems/score/basedefs.h>
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef uint16_t Priority_bit_map_Control;
+typedef void i386_isr;
+typedef i386_isr ( *i386_isr_entry )( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
diff --git a/cpukit/score/cpu/i386/sse_test.c b/cpukit/score/cpu/i386/sse_test.c
new file mode 100644
index 0000000000..8b1cbd2658
--- /dev/null
+++ b/cpukit/score/cpu/i386/sse_test.c
@@ -0,0 +1,954 @@
+/* $Id$ */
+
+/*
+ * Authorship
+ * ----------
+ * This software was created by
+ * Till Straumann <strauman@slac.stanford.edu>, 2009,
+ * Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * This software was produced by
+ * the Stanford Linear Accelerator Center, Stanford University,
+ * under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software. Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+
+
+/* Code for testing FPU/SSE context save/restore across exceptions
+ * (including interrupts).
+ *
+ * There are two tasks and an IRQ/EXC handler involved. One task (LP)
+ * is of lower priority than the other (HP) task.
+ *
+ * 1) LP task sets up a context area in memory (known contents; every
+ * register is loaded with different values)
+ *
+ * 2) LP task
+ * 2a saves original FP/SSE context
+ * 2b loads context from 1) into FPU/SSE
+ * 2c raises an exception or interrupt
+ *
+ * * (2d save FPU/SSE context after irq/exception returns to
+ * separate area for verification
+ * 2e reload original FP/SSE context.)
+ *
+ * * All these five steps are coded in assembly to prevent
+ * gcc from manipulating the FP/SSE state. The last two steps,
+ * however, are effectively executed during 6 when control is
+ * returned to the LP task.
+ *
+ * 3) IRQ/EXC handler OS wrapper saves context, initializes FPU and
+ * MXCSR.
+ *
+ * 4) user (our) irq/exc handler clears exception condition, clobbers
+ * FPU and XMM regs and finally releases a semaphore on which HP
+ * task is waiting.
+ *
+ * 5) context switch to HP task. HP task clobbers FPU and XMM regs.
+ * Then it tries to re-acquire the synchronization semaphore and
+ * blocks.
+ *
+ * 6) task switch back to (interrupted) LP task. Original context is
+ * restored and verified against the context that was setup in 1).
+ *
+ *
+ * Three methods for interrupting the LP task are tested
+ *
+ * a) FP exception (by setting an exception status in the context from 1)
+ * b) SSE exception (by computing the square root of a vector of negative
+ * numbers.
+ * c) IRQ (software IRQ via 'INT xx' instruction)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef __rtems__
+#include <rtems.h>
+#include <rtems/score/cpu.h>
+#include <rtems/irq.h>
+#include <rtems/error.h>
+#endif
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+/* This is currently hardcoded (int xx opcode requires immediate operand) */
+#define SSE_TEST_IRQ 10
+
+typedef uint8_t __v8 __attribute__((vector_size(16)));
+typedef uint32_t __v32 __attribute__((vector_size(16)));
+typedef float __vf __attribute__((vector_size(16)));
+
+#ifndef __rtems__
+/* Clone of what is defined in rtems/score/cpu.h (for testing under linux) */
+typedef struct Context_Control_sse {
+ uint16_t fcw;
+ uint16_t fsw;
+ uint8_t ftw;
+ uint8_t res_1;
+ uint16_t fop;
+ uint32_t fpu_ip;
+ uint16_t cs;
+ uint16_t res_2;
+ uint32_t fpu_dp;
+ uint16_t ds;
+ uint16_t res_3;
+ uint32_t mxcsr;
+ uint32_t mxcsr_mask;
+ struct {
+ uint8_t fpreg[10];
+ uint8_t res_4[ 6];
+ } fp_mmregs[8];
+ uint8_t xmmregs[8][16];
+ uint8_t res_5[224];
+} Context_Control_sse
+__attribute__((aligned(16)))
+;
+#endif
+
+#define MXCSR_FZ (1<<15) /* Flush to zero */
+#define MXCSR_RC(x) (((x)&3)<<13) /* Rounding ctrl */
+#define MXCSR_PM (1<<12) /* Precision msk */
+#define MXCSR_UM (1<<11) /* Underflow msk */
+#define MXCSR_OM (1<<10) /* Overflow msk */
+#define MXCSR_ZM (1<< 9) /* Divbyzero msk */
+#define MXCSR_DM (1<< 8) /* Denormal msk */
+#define MXCSR_IM (1<< 7) /* Invalidop msk */
+#define MXCSR_DAZ (1<< 6) /* Denorml are 0 */
+#define MXCSR_PE (1<< 5) /* Precision flg */
+#define MXCSR_UE (1<< 4) /* Underflow flg */
+#define MXCSR_OE (1<< 3) /* Overflow flg */
+#define MXCSR_ZE (1<< 2) /* Divbyzero flg */
+#define MXCSR_DE (1<< 1) /* Denormal flg */
+#define MXCSR_IE (1<< 0) /* Invalidop flg */
+
+#define MXCSR_ALLM (MXCSR_PM | MXCSR_UM | MXCSR_OM | MXCSR_ZM | MXCSR_DM | MXCSR_IM)
+#define MXCSR_ALLE (MXCSR_PE | MXCSR_UE | MXCSR_OE | MXCSR_ZE | MXCSR_DE | MXCSR_IE)
+
+#define FPSR_B (1<<15) /* FPU busy */
+#define FPSR_C3 (1<<14) /* Cond code C3 */
+#define FPSR_TOP(x) (((x)&7)<<11) /* TOP */
+#define FPSR_C2 (1<<10) /* Cond code C2 */
+#define FPSR_C1 (1<< 9) /* Cond code C1 */
+#define FPSR_C0 (1<< 8) /* Cond code C0 */
+#define FPSR_ES (1<< 7) /* Error summary */
+#define FPSR_SF (1<< 6) /* Stack fault */
+#define FPSR_PE (1<< 5) /* Precision flg */
+#define FPSR_UE (1<< 4) /* Underflow flg */
+#define FPSR_OE (1<< 3) /* Overflow flg */
+#define FPSR_ZE (1<< 2) /* Divbyzero flg */
+#define FPSR_DE (1<< 1) /* Denormal flg */
+#define FPSR_IE (1<< 0) /* Invalidop flg */
+
+#define FPCW_X (1<<12) /* Infinity ctrl */
+#define FPCW_RC(x) (((x)&3)<<10) /* Rounding ctrl */
+#define FPCW_PC(x) (((x)&3)<< 8) /* Precision ctl */
+#define FPCW_PM (1<< 5) /* Precision msk */
+#define FPCW_UM (1<< 4) /* Underflow msk */
+#define FPCW_OM (1<< 3) /* Overflow msk */
+#define FPCW_ZM (1<< 2) /* Divbyzero msk */
+#define FPCW_DM (1<< 1) /* Denormal msk */
+#define FPCW_IM (1<< 0) /* Invalidop msk */
+
+#define FPCW_ALLM (FPCW_PM | FPCW_UM | FPCW_OM | FPCW_ZM | FPCW_DM | FPCW_IM)
+#define FPSR_ALLE (FPSR_ES | FPSR_SF | FPSR_PE | FPSR_UE | FPSR_OE | FPSR_ZE | FPSR_DE | FPSR_IE)
+
+/* Store 'double' into 80-bit register image */
+void
+fp_st1(uint8_t (*p_dst)[10], double v)
+{
+ asm volatile("fstpt %0":"=m"(*p_dst):"t"(v):"st");
+}
+
+/* Store 'double' into 80-bit register image #i in context */
+void
+fp_st(Context_Control_sse *p_ctxt, int i, double v)
+{
+ fp_st1(&p_ctxt->fp_mmregs[i].fpreg,v);
+}
+
+/* Load 'double' from 80-bit register image */
+double
+fp_ld1(uint8_t (*p_src)[10])
+{
+double v;
+
+ asm volatile("fldt %1":"=t"(v):"m"((*p_src)[0]),"m"(*p_src));
+ return v;
+}
+
+/* Load 'double' from 80-bit register image #i in context */
+double
+fp_ld(Context_Control_sse *p_ctxt, int i)
+{
+ return fp_ld1(&p_ctxt->fp_mmregs[i].fpreg);
+}
+
+#define FPUCLOBBER \
+ "st","st(1)","st(2)","st(3)", \
+ "st(4)","st(5)","st(6)","st(7)",\
+ "fpsr","fpcr"
+
+/* There seems to be no way to say that mxcsr was clobbered */
+
+#define SSECLOBBER \
+ "xmm0","xmm1","xmm2","xmm3", \
+ "xmm4","xmm5","xmm6","xmm7"
+
+static void
+sse_clobber(uint32_t x)
+{
+__v32 v = { x, x, x, x };
+ asm volatile (
+ " movdqa %0, %%xmm0 \n"
+ " movdqa %%xmm0, %%xmm1 \n"
+ " movdqa %%xmm0, %%xmm2 \n"
+ " movdqa %%xmm0, %%xmm3 \n"
+ " movdqa %%xmm0, %%xmm4 \n"
+ " movdqa %%xmm0, %%xmm5 \n"
+ " movdqa %%xmm0, %%xmm6 \n"
+ " movdqa %%xmm0, %%xmm7 \n"
+ :
+ :"m"(v)
+ :SSECLOBBER
+ );
+}
+
+void
+all_clobber(uint32_t v1, uint32_t v2);
+
+__asm__ (
+"all_clobber: \n"
+" finit \n"
+" movq 0(%esp), %xmm0 \n"
+" punpcklqdq %xmm0, %xmm0 \n"
+" movdqa %xmm0, %xmm1 \n"
+" movdqa %xmm0, %xmm2 \n"
+" movdqa %xmm0, %xmm3 \n"
+" movdqa %xmm0, %xmm4 \n"
+" movdqa %xmm0, %xmm5 \n"
+" movdqa %xmm0, %xmm6 \n"
+" movdqa %xmm0, %xmm7 \n"
+" ret \n"
+);
+
+/* Clear FPU and save FPU/SSE registers to context area */
+
+void
+init_ctxt(Context_Control_sse *p_ctxt);
+
+__asm__ (
+"init_ctxt: \n"
+" finit \n"
+" mov 4(%esp), %eax\n"
+" fxsave (%eax) \n"
+" fwait \n"
+" ret \n"
+);
+
+/* Save FPU/SSE registers to context area */
+
+static void
+stor_ctxt(Context_Control_sse *p_ctxt)
+{
+ memset(p_ctxt, 0, sizeof(*p_ctxt));
+ asm volatile(
+/* " finit \n" */
+ " fxsave %0 \n"
+ " fwait \n"
+ : "=m"(*p_ctxt)
+ :
+ : FPUCLOBBER
+ );
+}
+
+#define H08 "0x%02"PRIx8
+#define H16 "0x%04"PRIx16
+#define H32 "0x%08"PRIx32
+
+#define F16 "mismatch ("H16" != "H16")\n"
+
+#define FLDCMP(fld, fmt) \
+ if ( a->fld != b->fld ) { \
+ rval = 1; \
+ if ( !quiet ) \
+ fprintf(stderr,#fld" mismatch ("fmt" != "fmt")\n",a->fld, b->fld); \
+ }
+
+#define FLTCMP(i) \
+ do { \
+ if ( ( (a->ftw ^ b->ftw) & (1<<i)) \
+ || ( (a->ftw & b->ftw & (1<<i)) && \
+ memcmp(a->fp_mmregs[i].fpreg, \
+ b->fp_mmregs[i].fpreg, \
+ sizeof(a->fp_mmregs[i].fpreg)) \
+ ) \
+ ) { \
+ rval = 1; \
+ if ( !quiet ) { \
+ double fa = fp_ld(a, i); \
+ double fb = fp_ld(b, i); \
+ if ( ((a->ftw ^ b->ftw) & (1<<i)) ) \
+ fprintf(stderr,"fpreg[%u] TAG mismatch (%u != %u)\n",i,(a->ftw & (1<<i)) ? 1 : 0,(b->ftw & (1<<i)) ? 1 : 0); \
+ else \
+ fprintf(stderr,"fpreg[%u] mismatch (%g != %g)\n",i,fa,fb); \
+ } \
+ } \
+ } while (0)
+
+#define XMMCMP(i) \
+ do { \
+ if ( memcmp(&a->xmmregs[i], \
+ &b->xmmregs[i], \
+ sizeof(a->xmmregs[i])) \
+ ) { \
+ rval = 1; \
+ if ( !quiet ) { \
+ int _jj; \
+ fprintf(stderr,"xmmreg[%u] mismatch:\n", i); \
+ fprintf(stderr," "); \
+ for (_jj=0; _jj<16; _jj++) \
+ fprintf(stderr,"%02x ",a->xmmregs[i][_jj]); \
+ fprintf(stderr,"\n !=\n"); \
+ fprintf(stderr," "); \
+ for (_jj=0; _jj<16; _jj++) \
+ fprintf(stderr,"%02x ",b->xmmregs[i][_jj]); \
+ fprintf(stderr,"\n"); \
+ } \
+ } \
+ } while (0)
+
+
+/* Compare two FPU/SSE context areas and flag differences;
+ * RETURNS: zero if the contexts match and nonzero otherwise
+ */
+static int
+cmp_ctxt(Context_Control_sse *a, Context_Control_sse *b, int quiet)
+{
+int rval = 0;
+int i;
+ FLDCMP(fcw,H16);
+ FLDCMP(fsw,H16);
+ FLDCMP(ftw,H08);
+ FLDCMP(fop,H16);
+ FLDCMP(fpu_ip,H32);
+ FLDCMP(cs,H16);
+ FLDCMP(fpu_dp,H32);
+ FLDCMP(ds,H16);
+ FLDCMP(mxcsr,H32);
+ FLDCMP(mxcsr_mask,H32);
+ for ( i=0; i<8; i++ ) {
+ FLTCMP(i);
+ }
+ for ( i=0; i<8; i++ ) {
+ XMMCMP(i);
+ }
+ return rval;
+}
+
+/* Possible arguments to exc_raise() */
+
+#define FP_EXC 0
+#define IRQ_EXC 1
+#define SSE_EXC -1
+
+/* Check stack alignment by raising the interrupt from a
+ * non-16-byte aligned section of code. The exception/IRQ
+ * handler must align the stack and SSE context area
+ * properly or it will crash.
+ */
+#define __INTRAISE(x) " int $32+"#x" \n"
+#define INTRAISE(x) __INTRAISE(x)
+
+__asm__ (
+"do_raise: \n"
+" fwait \n"
+" test %eax, %eax \n"
+" je 2f \n"
+" jl 1f \n"
+INTRAISE(SSE_TEST_IRQ)
+" jmp 2f \n"
+"1: sqrtps %xmm0, %xmm0 \n"
+"2: \n"
+" ret \n"
+);
+
+#define SSE_TEST_HP_FAILED 1
+#define SSE_TEST_FSPR_FAILED 2
+#define SSE_TEST_CTXTCMP_FAILED 4
+
+static const char *fail_msgs[] = {
+ "Seems that HP task was not executing",
+ "FPSR 'Invalid-operation' flag should be clear",
+ "Restored context does NOT match the saved one",
+};
+
+static void prstat(int st, const char *where)
+{
+int i,msk;
+ for ( i=0, msk=1; i<sizeof(fail_msgs)/sizeof(fail_msgs[0]); i++, msk<<=1 ) {
+ if ( (st & msk) ) {
+ fprintf(stderr,"sse_test ERROR: %s (testing: %s)\n", fail_msgs[i], where);
+ }
+ }
+}
+
+int sse_test_debug = 0;
+
+static int
+exc_raise(int kind)
+{
+Context_Control_sse nctxt;
+Context_Control_sse octxt;
+Context_Control_sse orig_ctxt;
+int i,j,rval;
+double s2;
+uint16_t fsw;
+__vf f4 = { -1., -2., -3., -4. };
+__vf tmp;
+__v32 sgn = { (1<<31), (1<<31), (1<<31), (1<<31) };
+
+ stor_ctxt(&octxt);
+
+ octxt.fsw &= ~FPSR_ALLE;
+ octxt.mxcsr &= ~MXCSR_ALLE;
+
+ for ( i=0; i<8; i++ ) {
+ fp_st(&octxt, i, (double)i+0.1);
+ for (j=0; j<16; j++) {
+ octxt.xmmregs[i][j]=(i<<4)+j;
+ }
+ }
+
+
+ if ( SSE_EXC == kind ) {
+ memcpy(octxt.xmmregs[0], &f4, sizeof(f4));
+ octxt.mxcsr &= ~MXCSR_IM;
+ }
+
+ /* set tags to 'valid' */
+ octxt.ftw = 0xff;
+
+ /* enable 'invalid arg' exception */
+ octxt.fcw &= ~ ( FPCW_IM );
+
+ if ( FP_EXC == kind ) {
+ octxt.fsw |= ( FPSR_IE | FPSR_ES );
+ }
+
+ if ( sse_test_debug )
+ printk("RAISE (fsw was 0x%04x)\n", orig_ctxt.fsw);
+ asm volatile(
+ " fxsave %2 \n"
+#ifdef __rtems__
+ " movl %4, sse_test_check\n"
+#endif
+ " fxrstor %3 \n"
+ " call do_raise \n"
+#ifdef __rtems__
+ " movl sse_test_check, %1\n"
+#else
+ " movl $0, %1 \n"
+#endif
+#ifdef TEST_MISMATCH
+ " pxor %%xmm0, %%xmm0 \n"
+#endif
+ " fxsave %0 \n"
+ " fxrstor %2 \n"
+ : "=m"(nctxt),"=&r"(rval),"=m"(orig_ctxt)
+ : "m"(octxt), "i"(SSE_TEST_HP_FAILED),"a"(kind)
+ : "xmm0"
+ );
+
+ if ( ( FPSR_IE & nctxt.fsw ) ) {
+ rval |= SSE_TEST_FSPR_FAILED;
+ }
+ if ( FP_EXC == kind )
+ nctxt.fsw |= (FPSR_IE | FPSR_ES);
+ else if ( SSE_EXC == kind ) {
+ tmp = __builtin_ia32_sqrtps( (__vf)(~sgn & (__v32)f4) );
+ /* sqrt raises PE; just clear it */
+ nctxt.mxcsr &= ~MXCSR_PE;
+ memcpy( octxt.xmmregs[0], &tmp, sizeof(tmp) );
+ }
+
+ if ( cmp_ctxt(&nctxt, &octxt, 0) ) {
+ rval |= SSE_TEST_CTXTCMP_FAILED;
+ }
+
+ s2 = sqrt(2.0);
+
+ asm volatile("fstsw %0":"=m"(fsw));
+
+ if ( sse_test_debug )
+ printf("sqrt(2): %f (FSTW: 0x%02"PRIx16")\n", sqrt(2.0), fsw);
+
+ return rval;
+}
+
+#ifdef __rtems__
+static void
+sse_test_ehdl(CPU_Exception_frame *p_f);
+
+rtems_id sse_test_sync = 0;
+cpuExcHandlerType sse_test_ohdl = 0;
+
+CPU_Exception_frame *sse_test_frame = 0;
+volatile int sse_test_check = SSE_TEST_HP_FAILED;
+unsigned sse_tests = 0;
+
+rtems_task
+sse_test_hp_task(rtems_task_argument arg)
+{
+rtems_id sync = (rtems_id)arg;
+
+uint16_t fp_cw;
+uint32_t mxcsr;
+rtems_status_code sc;
+const char * msgs[] = {"FPU_EXC", "SSE_EXC", "IRQ_EXC"};
+int i;
+
+ /* verify that FPU control word is default value */
+ asm volatile("fstcw %0":"=m"(fp_cw));
+ if ( fp_cw != _CPU_Null_fp_context.fpucw ) {
+ fprintf(
+ stderr,
+ "ERROR: FPU CW initialization mismatch: got 0x%04"PRIx16"; expected 0x%04"PRIx16"\n",
+ fp_cw,
+ _CPU_Null_fp_context.fpucw
+ );
+ }
+
+ /* check MXCSR default value */
+ asm volatile("stmxcsr %0":"=m"(mxcsr));
+ if ( mxcsr != _CPU_Null_fp_context.mxcsr ) {
+ fprintf(
+ stderr,
+ "ERROR: MXCSR initialization mismatch: got 0x%08"PRIx32"; expected 0x%08"PRIx32"\n",
+ mxcsr,
+ _CPU_Null_fp_context.mxcsr
+ );
+ }
+
+
+ for (i=0; i<sizeof(msgs)/sizeof(msgs[0]); i++ ) {
+ if ( ( sse_tests & (1<<i) ) ) {
+ if ( sse_test_debug )
+ printk("HP task will now block for %s\n",msgs[i]);
+
+ /* Blocking here lets the low-priority task continue */
+ sc = rtems_semaphore_obtain(sync, RTEMS_WAIT, 500);
+
+ all_clobber(0xaffeaffe, 0xcafecafe);
+
+ if ( RTEMS_SUCCESSFUL != sc ) {
+ rtems_error(sc,"ERROR: sse_test hp task wasn't notified of exception\n");
+ goto bail;
+ }
+
+ /* set flag indicating that we executed until here */
+ sse_test_check = 0;
+ }
+ }
+
+bail:
+ rtems_task_suspend(RTEMS_SELF);
+}
+
+/* Flags to skip individual tests */
+#define SSE_TEST_FPU_EXC (1<<0)
+#define SSE_TEST_SSE_EXC (1<<1)
+#define SSE_TEST_IRQ_EXC (1<<2)
+
+#define SSE_TEST_ALL 7
+
+/* If this flag is given the executing task is not deleted
+ * when the test finishes. This is useful if you want to
+ * execute from a shell or similar.
+ */
+#define SSE_TEST_NO_DEL (1<<0)
+
+/* Task arg is bitmask of these flags */
+rtems_task
+sse_test_lp_task(rtems_task_argument arg)
+{
+rtems_id hp_task = 0;
+rtems_status_code sc;
+rtems_task_priority pri;
+uint16_t fp_cw,fp_cw_set;
+uint32_t mxcsr, mxcsr_set;
+rtems_irq_connect_data irqd;
+int flags = (int)arg;
+int st;
+int errs = 0;
+
+ sse_tests = SSE_TEST_ALL & ~(flags>>1);
+
+ sse_test_ohdl = 0;
+
+ fp_cw_set = _CPU_Null_fp_context.fpucw | FPCW_RC(3) ;
+ mxcsr_set = _CPU_Null_fp_context.mxcsr | MXCSR_RC(3) ;
+ asm volatile("ldmxcsr %0"::"m"(mxcsr_set));
+ asm volatile("fldcw %0"::"m"(fp_cw_set));
+
+ sc = rtems_semaphore_create(
+ rtems_build_name('s','s','e','S'),
+ 0,
+ RTEMS_SIMPLE_BINARY_SEMAPHORE,
+ 0,
+ &sse_test_sync
+ );
+ if ( RTEMS_SUCCESSFUL != sc ) {
+ rtems_error(sc, "sse_test ERROR: creation of 'sync' semaphore failed");
+ errs++;
+ goto bail;
+ }
+
+ rtems_task_set_priority( RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &pri );
+
+ sc = rtems_task_create(
+ rtems_build_name('s','s','e','H'),
+ pri - 2,
+ 20000,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_FLOATING_POINT,
+ &hp_task
+ );
+ if ( RTEMS_SUCCESSFUL != sc ) {
+ hp_task = 0;
+ rtems_error( sc, "sse_test ERROR: creation of high-priority task failed");
+ errs++;
+ goto bail;
+ }
+
+ sc = rtems_task_start( hp_task, sse_test_hp_task, (rtems_task_argument)sse_test_sync );
+ if ( RTEMS_SUCCESSFUL != sc ) {
+ rtems_error( sc, "sse_test ERROR: start of high-priority task failed");
+ goto bail;
+ }
+
+ /* Test if FP/SSE context is saved/restored across an exception */
+ sse_test_ohdl = _currentExcHandler;
+ _currentExcHandler = sse_test_ehdl;
+
+ if ( (sse_tests & SSE_TEST_FPU_EXC) ) {
+ if ( (st = exc_raise(FP_EXC)) ) {
+ prstat(st,"FP_EXC");
+ errs++;
+ }
+
+ /* Test modified FPCW/MXCSR */
+ asm volatile("fstcw %0":"=m"(fp_cw));
+ asm volatile("stmxcsr %0":"=m"(mxcsr));
+ mxcsr &= ~(MXCSR_ALLE);
+ if ( fp_cw != fp_cw_set ) {
+ fprintf(stderr,"sse_test ERROR: FPCW mismatch (after FP_EXC): expected 0x%04"PRIx16", got 0x%04"PRIx16"\n", fp_cw_set, fp_cw);
+ errs++;
+ }
+ if ( mxcsr != mxcsr_set ) {
+ fprintf(stderr,"sse_test ERROR: MXCSR mismatch (after FP_EXC): expected 0x%08"PRIx32", got 0x%08"PRIx32"\n", mxcsr_set, mxcsr);
+ errs++;
+ }
+ }
+
+ if ( (sse_tests & SSE_TEST_SSE_EXC) ) {
+ if ( (st = exc_raise(SSE_EXC)) ) {
+ prstat(st, "SSE_EXC");
+ errs++;
+ }
+
+ /* Test modified FPCW/MXCSR */
+ asm volatile("fstcw %0":"=m"(fp_cw));
+ asm volatile("stmxcsr %0":"=m"(mxcsr));
+ mxcsr &= ~(MXCSR_ALLE);
+ if ( fp_cw != fp_cw_set ) {
+ fprintf(stderr,"sse_test ERROR: FPCW mismatch (after SSE_EXC): expected 0x%04"PRIx16", got 0x%04"PRIx16"\n", fp_cw_set, fp_cw);
+ errs++;
+ }
+ if ( mxcsr != mxcsr_set ) {
+ fprintf(stderr,"sse_test ERROR: MXCSR mismatch (after SSE_EXC): expected 0x%08"PRIx32", got 0x%08"PRIx32"\n", mxcsr_set, mxcsr);
+ errs++;
+ }
+ }
+
+
+ if ( (sse_tests & SSE_TEST_IRQ_EXC) ) {
+ memset( &irqd, 0, sizeof(irqd) );
+ irqd.name = SSE_TEST_IRQ;
+ irqd.hdl = (void*)sse_test_ehdl;
+ irqd.handle = 0;
+
+ if ( ! BSP_install_rtems_irq_handler( &irqd ) ) {
+ fprintf(stderr, "sse_test ERROR: Unable to install ISR\n");
+ errs++;
+ goto bail;
+ }
+
+ /* Test if FP/SSE context is saved/restored across an interrupt */
+ if ( (st = exc_raise(IRQ_EXC)) ) {
+ prstat(st, "IRQ");
+ errs++;
+ }
+
+ if ( ! BSP_remove_rtems_irq_handler( &irqd ) ) {
+ fprintf(stderr, "sse_test ERROR: Unable to uninstall ISR\n");
+ }
+
+ /* Test modified FPCW/MXCSR */
+ asm volatile("fstcw %0":"=m"(fp_cw));
+ asm volatile("stmxcsr %0":"=m"(mxcsr));
+ mxcsr &= ~(MXCSR_ALLE);
+ if ( fp_cw != fp_cw_set ) {
+ fprintf(stderr,"sse_test ERROR: FPCW mismatch (after IRQ): expected 0x%04"PRIx16", got 0x%04"PRIx16"\n", fp_cw_set, fp_cw);
+ errs++;
+ }
+ if ( mxcsr != mxcsr_set ) {
+ fprintf(stderr,"sse_test ERROR: MXCSR mismatch (after IRQ): expected 0x%08"PRIx32", got 0x%08"PRIx32"\n", mxcsr_set, mxcsr);
+ errs++;
+ }
+ }
+
+
+bail:
+ /* Wait for console to calm down... */
+ rtems_task_wake_after(5);
+ fprintf(stderr,"SSE/FPU Test %s (%u errors)\n", errs ? "FAILED":"PASSED", errs);
+ if ( sse_test_ohdl ) {
+ _currentExcHandler = sse_test_ohdl;
+ sse_test_ohdl = 0;
+ }
+ if ( sse_test_sync )
+ rtems_semaphore_delete( sse_test_sync );
+ sse_test_sync = 0;
+ if ( hp_task )
+ rtems_task_delete( hp_task );
+
+ if ( ! (flags & SSE_TEST_NO_DEL) )
+ rtems_task_delete( RTEMS_SELF );
+}
+
+static void
+sse_test_ehdl(CPU_Exception_frame *p_f)
+{
+int i,j,start = 0;
+int mismatch;
+__vf f4;
+
+ if ( p_f ) {
+ printk("Got exception #%u\n", p_f->idtIndex);
+ printk("EIP: 0x%08x, ESP: 0x%08x\n", p_f->eip, p_f->esp0);
+ printk("TID: 0x%08x\n", _Thread_Executing->Object.id);
+
+ if ( ! p_f->fp_ctxt ) {
+ printk("ERROR: NO FP/SSE CONTEXT ATTACHED ??\n");
+ sse_test_ohdl(p_f);
+ }
+ if ( 16 == p_f->idtIndex ) {
+ printk("Resetting FP status (0x%04"PRIx16")\n", p_f->fp_ctxt->fsw);
+ p_f->fp_ctxt->fsw = 0;
+ } else if ( 19 == p_f->idtIndex ) {
+ start = 1;
+ memcpy(&f4, p_f->fp_ctxt->xmmregs[0], sizeof(f4));
+ f4 = -f4;
+ memcpy(p_f->fp_ctxt->xmmregs[0], &f4, sizeof(f4));
+ p_f->fp_ctxt->mxcsr &= ~MXCSR_ALLE;
+ } else {
+ printk("(skipping non-FP exception)\n");
+ sse_test_ohdl(p_f);
+ }
+
+ printk("Checking XMM regs -- ");
+ for ( mismatch=0, i=start; i<8; i++ ) {
+ for ( j=0; j<16; j++ ) {
+ if ( p_f->fp_ctxt->xmmregs[i][j] != ((i<<4) | j) )
+ mismatch++;
+ }
+ }
+ if ( mismatch ) {
+ printk("%u mismatches; dump:\n", mismatch);
+ for ( i=0; i<8; i++ ) {
+ for ( j=0; j<16; j++ ) {
+ printk("0x%02x ", p_f->fp_ctxt->xmmregs[i][j]);
+ }
+ printk("\n");
+ }
+ } else {
+ printk("OK\n");
+ }
+ } else {
+ printk("IRQ %u\n", SSE_TEST_IRQ);
+ }
+ printk("Clobbering FPU/SSE state\n");
+ asm volatile("finit");
+ sse_clobber(0xdeadbeef);
+ printk("Notifying task\n");
+ rtems_semaphore_release( sse_test_sync );
+}
+
+#else
+
+/* Code using signals for testing under linux; unfortunately, 32-bit
+ * linux seems to pass no SSE context info to the sigaction...
+ */
+
+#include <signal.h>
+#include <ucontext.h>
+
+#define MKCASE(X) case FPE_##X: msg="FPE_"#X; break;
+
+#define CLRXMM(i) __asm__ volatile("pxor %%xmm"#i", %%xmm"#i:::"xmm"#i)
+
+static void
+fpe_act(int signum, siginfo_t *p_info, void *arg3)
+{
+ucontext_t *p_ctxt = arg3;
+const char *msg = "FPE_UNKNOWN";
+uint16_t *p_fst;
+
+ if ( SIGFPE != signum ) {
+ fprintf(stderr,"WARNING: fpe_act handles SIGFPE\n");
+ return;
+ }
+ switch ( p_info->si_code ) {
+ default:
+ fprintf(stderr,"WARNING: fpe_act got unkown code %u\n", p_info->si_code);
+ return;
+ MKCASE(INTDIV);
+ MKCASE(INTOVF);
+ MKCASE(FLTDIV);
+ MKCASE(FLTOVF);
+ MKCASE(FLTUND);
+ MKCASE(FLTRES);
+ MKCASE(FLTINV);
+ MKCASE(FLTSUB);
+ }
+ fprintf(stderr,"Got SIGFPE (%s) @%p\n", msg, p_info->si_addr);
+#ifdef __linux__
+ fprintf(stderr,"Resetting FP status 0x%02lx\n", p_ctxt->uc_mcontext.fpregs->sw);
+ p_ctxt->uc_mcontext.fpregs->sw = 0;
+#ifdef TEST_MISMATCH
+ fp_st1((void*)&p_ctxt->uc_mcontext.fpregs->_st[3],2.345);
+#endif
+#endif
+
+ /* Clear FPU; if context is properly saved/restored around exception
+ * then this shouldn't disturb the register contents of the interrupted
+ * task/process.
+ */
+ asm volatile("finit");
+ sse_clobber(0xdeadbeef);
+}
+
+static void
+test(void)
+{
+Context_Control_sse ctxt;
+
+ stor_ctxt(&ctxt);
+ printf("FPCW: 0x%"PRIx16"\nFPSW: 0x%"PRIx16"\n", ctxt.fcw, ctxt.fsw);
+ printf("FTAG: 0x%"PRIx8"\n",ctxt.ftw);
+}
+
+int
+main(int argc, char **argv)
+{
+struct sigaction a1, a2;
+uint32_t mxcsr;
+
+ memset(&a1, 0, sizeof(a1));
+
+ a1.sa_sigaction = fpe_act;
+ a1.sa_flags = SA_SIGINFO;
+
+ if ( sigaction(SIGFPE, &a1, &a2) ) {
+ perror("sigaction");
+ return 1;
+ }
+
+ asm volatile("stmxcsr %0":"=m"(mxcsr));
+ printf("MXCSR: 0x%08"PRIx32"\n", mxcsr);
+
+ test();
+ exc_raise(0);
+ return 0;
+}
+#endif
+
+/* Helpers to access CR4 and MXCSR */
+
+uint32_t
+mfcr4()
+{
+uint32_t rval;
+ asm volatile("mov %%cr4, %0":"=r"(rval));
+ return rval;
+}
+
+void
+mtcr4(uint32_t rval)
+{
+ asm volatile("mov %0, %%cr4"::"r"(rval));
+}
+
+uint32_t
+mfmxcsr()
+{
+uint32_t rval;
+ asm volatile("stmxcsr %0":"=m"(rval));
+ return rval;
+}
+
+void
+mtmxcsr(uint32_t rval)
+{
+ asm volatile("ldmxcsr %0"::"m"(rval));
+}
+
+
+float
+sseraise()
+{
+__vf f4={-2., -2., -2. -2.};
+float f;
+ f4 = __builtin_ia32_sqrtps( f4 );
+ memcpy(&f,&f4,sizeof(f));
+ return f;
+}