summaryrefslogtreecommitdiff
path: root/ext/systemc/src/sysc/qt
diff options
context:
space:
mode:
authorMatthias Jung <jungma@eit.uni-kl.de>2017-03-01 18:39:56 +0100
committerMatthias Jung <jungma@eit.uni-kl.de>2017-05-18 08:36:56 +0000
commitaa651c7f8321bf96fc88f9a17285225000a753ec (patch)
treeb13240008c970b47bd74a5007e68136155d272fc /ext/systemc/src/sysc/qt
parent595e692de09e1b7cbc5f57ac01da299afc066fdd (diff)
downloadgem5-aa651c7f8321bf96fc88f9a17285225000a753ec.tar.xz
ext: Include SystemC 2.3.1 into gem5
In the past it happened several times that some changes in gem5 broke the SystemC coupling. Recently Accelera has changed the licence for SystemC from their own licence to Apache2.0, which is compatible with gem5. However, SystemC usually relies on the Boost library, but I was able to exchange the boost calls by c++11 alternatives. The recent SystemC version is placed into /ext and is integrated into gem5's build system. The goal is to integrate some SystemC tests for the CI in some following patches. Change-Id: I4b66ec806b5e3cffc1d7c85d3735ff4fa5b31fd0 Reviewed-on: https://gem5-review.googlesource.com/2240 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Diffstat (limited to 'ext/systemc/src/sysc/qt')
-rw-r--r--ext/systemc/src/sysc/qt/CHANGES15
-rw-r--r--ext/systemc/src/sysc/qt/INSTALL81
-rw-r--r--ext/systemc/src/sysc/qt/README89
-rw-r--r--ext/systemc/src/sysc/qt/README.MISC56
-rw-r--r--ext/systemc/src/sysc/qt/README.PORT112
-rw-r--r--ext/systemc/src/sysc/qt/b.h11
-rwxr-xr-xext/systemc/src/sysc/qt/config392
-rw-r--r--ext/systemc/src/sysc/qt/copyright.h12
-rw-r--r--ext/systemc/src/sysc/qt/md/axp.1.Makefile5
-rw-r--r--ext/systemc/src/sysc/qt/md/axp.2.Makefile5
-rw-r--r--ext/systemc/src/sysc/qt/md/axp.Makefile5
-rw-r--r--ext/systemc/src/sysc/qt/md/axp.README10
-rw-r--r--ext/systemc/src/sysc/qt/md/axp.c133
-rw-r--r--ext/systemc/src/sysc/qt/md/axp.h160
-rw-r--r--ext/systemc/src/sysc/qt/md/axp.s160
-rw-r--r--ext/systemc/src/sysc/qt/md/axp_b.s111
-rw-r--r--ext/systemc/src/sysc/qt/md/default.Makefile8
-rw-r--r--ext/systemc/src/sysc/qt/md/hppa-cnx.Makefile9
-rw-r--r--ext/systemc/src/sysc/qt/md/hppa.Makefile12
-rw-r--r--ext/systemc/src/sysc/qt/md/hppa.h196
-rw-r--r--ext/systemc/src/sysc/qt/md/hppa.s237
-rw-r--r--ext/systemc/src/sysc/qt/md/hppa_b.s203
-rw-r--r--ext/systemc/src/sysc/qt/md/i386.README7
-rw-r--r--ext/systemc/src/sysc/qt/md/i386.h132
-rw-r--r--ext/systemc/src/sysc/qt/md/i386.s119
-rw-r--r--ext/systemc/src/sysc/qt/md/i386_b.s30
-rw-r--r--ext/systemc/src/sysc/qt/md/iX86_64.h140
-rw-r--r--ext/systemc/src/sysc/qt/md/iX86_64.s74
-rw-r--r--ext/systemc/src/sysc/qt/md/ksr1.Makefile6
-rw-r--r--ext/systemc/src/sysc/qt/md/ksr1.h164
-rw-r--r--ext/systemc/src/sysc/qt/md/ksr1.s424
-rw-r--r--ext/systemc/src/sysc/qt/md/ksr1_b.s49
-rw-r--r--ext/systemc/src/sysc/qt/md/m88k.Makefile6
-rw-r--r--ext/systemc/src/sysc/qt/md/m88k.c111
-rw-r--r--ext/systemc/src/sysc/qt/md/m88k.h159
-rw-r--r--ext/systemc/src/sysc/qt/md/m88k.s132
-rw-r--r--ext/systemc/src/sysc/qt/md/m88k_b.s117
-rw-r--r--ext/systemc/src/sysc/qt/md/mips-irix5.s182
-rw-r--r--ext/systemc/src/sysc/qt/md/mips.h134
-rw-r--r--ext/systemc/src/sysc/qt/md/mips.s164
-rw-r--r--ext/systemc/src/sysc/qt/md/mips_b.s99
-rw-r--r--ext/systemc/src/sysc/qt/md/null.README0
-rw-r--r--ext/systemc/src/sysc/qt/md/null.c14
-rw-r--r--ext/systemc/src/sysc/qt/md/null.s12
-rw-r--r--ext/systemc/src/sysc/qt/md/powerpc.README27
-rw-r--r--ext/systemc/src/sysc/qt/md/powerpc.c69
-rw-r--r--ext/systemc/src/sysc/qt/md/powerpc_mach.h611
-rw-r--r--ext/systemc/src/sysc/qt/md/powerpc_mach.s641
-rw-r--r--ext/systemc/src/sysc/qt/md/powerpc_mach_b.s290
-rw-r--r--ext/systemc/src/sysc/qt/md/powerpc_sys5.h566
-rw-r--r--ext/systemc/src/sysc/qt/md/powerpc_sys5.s639
-rw-r--r--ext/systemc/src/sysc/qt/md/powerpc_sys5_b.s290
-rw-r--r--ext/systemc/src/sysc/qt/md/pthreads.Makefile108
-rw-r--r--ext/systemc/src/sysc/qt/md/solaris.README19
-rw-r--r--ext/systemc/src/sysc/qt/md/sparc.h140
-rw-r--r--ext/systemc/src/sysc/qt/md/sparc.s142
-rw-r--r--ext/systemc/src/sysc/qt/md/sparc_b.s106
-rw-r--r--ext/systemc/src/sysc/qt/md/vax.h130
-rw-r--r--ext/systemc/src/sysc/qt/md/vax.s69
-rw-r--r--ext/systemc/src/sysc/qt/md/vax_b.s92
-rw-r--r--ext/systemc/src/sysc/qt/meas.c1049
-rw-r--r--ext/systemc/src/sysc/qt/qt.c56
-rw-r--r--ext/systemc/src/sysc/qt/qt.h192
-rw-r--r--ext/systemc/src/sysc/qt/qtmd.h13
-rw-r--r--ext/systemc/src/sysc/qt/stp.c199
-rw-r--r--ext/systemc/src/sysc/qt/stp.h51
-rw-r--r--ext/systemc/src/sysc/qt/time/README.time17
-rwxr-xr-xext/systemc/src/sysc/qt/time/assim42
-rwxr-xr-xext/systemc/src/sysc/qt/time/cswap37
-rwxr-xr-xext/systemc/src/sysc/qt/time/go43
-rwxr-xr-xext/systemc/src/sysc/qt/time/init42
-rwxr-xr-xext/systemc/src/sysc/qt/time/prim41
-rwxr-xr-xext/systemc/src/sysc/qt/time/raw58
73 files changed, 10076 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/qt/CHANGES b/ext/systemc/src/sysc/qt/CHANGES
new file mode 100644
index 000000000..1b74921ee
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/CHANGES
@@ -0,0 +1,15 @@
+QuickThreads 002: Changes since QuickThreads 001.
+
+ - Now can be used by C++ programs.
+ - Now *really* works with stacks that grow up.
+ - Supports AXP OSF 2.x cc's varargs.
+ - Supports HP Precision (HP-PA) on workstations and Convex.
+ - Supports assemblers for Intel iX86 ith only '//'-style comments.
+ - Supports Silicon Graphics Irix 5.x with dynamic linking.
+ - Supports System V and Solaris 2.x with no `_' on compiler-generated
+ identifiers; *some* platforms only.
+
+Note: not all "./config" arguments are compatible with QT 001.
+
+
+QuickThreads 001: Base version.
diff --git a/ext/systemc/src/sysc/qt/INSTALL b/ext/systemc/src/sysc/qt/INSTALL
new file mode 100644
index 000000000..5b20f5d5e
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/INSTALL
@@ -0,0 +1,81 @@
+Installation of the `QuickThreads' threads-building toolkit.
+
+* Notice
+
+QuickThreads -- Threads-building toolkit.
+Copyright (c) 1993 by David Keppel
+
+Permission to use, copy, modify and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice and this notice
+appear in all copies. This software is provided as a
+proof-of-concept and for demonstration purposes; there is no
+representation about the suitability of this software for any
+purpose.
+
+
+* Configuration
+
+Configure with
+
+ ./config *machtype*
+
+where "*machtype*" is one of the supported target machines. As of
+October 1994, the supported machines (targets) are:
+
+ axp -- All Digital Equipment Corporation AXP (DEC Alpha)
+ processors, compile with GNU CC
+ axp-osf1 -- AXP running OSF 1.x
+ axp-osf2 -- AXP running OSF 2.x
+ hppa -- HP's PA-RISC 1.1 processor
+ hppa-cnx-spp -- Convex SPP (PA-RISC 1.1 processor)
+ iX86 -- 80386, 80486, and 80586-compatible processors
+ See notes below for OS/2.
+ iX86-ss -- 'iX86 for assemblers that use slash-slash ('//')
+ comments.
+ ksr1 -- All KSR processors
+ m88k -- All members of the Motorola 88000 family
+ mips -- MIPS R2000 and R3000 processors
+ mips-irix5 -- Irix 5.xx (use `mips' for Irix 4.xx)
+ sparc-os1 -- V8-compliant SPARC processors using compilers
+ that prefix labels (e.g. "foo" appears as "_foo")
+ Includes Solaris 1 (SunOS 4.X).
+ sparc-os2 -- V8-compliant SPARC processors using compilers
+ that do not prefix labels. Includes Solaris 2.
+ vax -- All VAX processors
+
+In addition, the target `clean' will deconfigure QuickThreads.
+
+Note that a given machine target may not work on all instances of that
+machine because e.g., the assembler syntax varies from machine to
+machine.
+
+Note also that additions to a processor family may require a new
+target. So, for example, the `vax' target might not work for all
+future VAX processors if, say, new VAX processors are introduced and
+they use separate floating-point registers.
+
+For OS/2, change `ranlib' to `ar -s', `configure' to `configure.cmd'
+(or was that `config' to `config.cmd'?), and replace the soft links
+(`ln -s') with plain copies.
+
+
+* Build
+
+To build the QuickThreads library, first configure (see above) then
+type `make libqt.a' in the top-level directory.
+
+To build the demonstration threads package, SimpleThreads, type
+`make libstp.a' in the top-level directory.
+
+To build an executable ``stress-test'' and measurement program, type
+`make run' in the top-level directory. Run `time/raw' to run the
+stress tests.
+
+
+* Installation
+
+Build the QuickThreads library (see above) and then copy `libqt.a' to
+the installation library directory (e.g., /usr/local/lib) and `qt.h'
+and `qtmd.h' to the installation include directory (e.g.,
+/usr/local/include).
diff --git a/ext/systemc/src/sysc/qt/README b/ext/systemc/src/sysc/qt/README
new file mode 100644
index 000000000..b014b91bf
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/README
@@ -0,0 +1,89 @@
+This is a source code distribution for QuickThreads. QuickThreads is a
+toolkit for building threads packages; it is described in detail in the
+University of Washington CS&E Technical report #93-05-06, available via
+anonymous ftp from `ftp.cs.washington.edu' (128.95.1.4, as of Oct. '94)
+in `tr/1993/05/UW-CSE-93-05-06.PS.Z'.
+
+This distribution shows basic ideas in QuickThreads and elaborates with
+example implementations for a gaggle of machines. As of October those
+machines included:
+
+ 80386 faimly
+ 88000 faimily
+ DEC AXP (Alpha) family
+ HP-PA family
+ KSR
+ MIPS family
+ SPARC V8 family
+ VAX family
+
+Configuration, build, and installation are described in INSTALL.
+
+Be aware: that there is no varargs code for the KSR.
+
+The HP-PA port was designed to work with both HP workstations
+and Convex SPP computers. It was generously provided by Uwe Reder
+<uereder@cip.informatik.uni-erlangen.de>. It is part of the ELiTE
+(Erlangen Lightweight Thread Environment) project directed by
+Frank Bellosa <bellosa@informatik.uni-erlangen.de> at the Operating
+Systems Department of the University of Erlangen (Germany).
+
+Other contributors include: Weihaw Chuang, Richard O'Keefe,
+Laurent Perron, John Polstra, Shinji Suzuki, Assar Westerlund,
+thanks also to Peter Buhr and Dirk Grunwald.
+
+
+Here is a brief summary:
+
+QuickThreads is a toolkit for building threads packages. It is my hope
+that you'll find it easier to use QuickThreads normally than to take it
+and modify the raw cswap code to fit your application. The idea behind
+QuickThreads is that it should make it easy for you to write & retarget
+threads packages. If you want the routine `t_create' to create threads
+and `t_block' to suspend threads, you write them using the QuickThreads
+`primitive' operations `QT_SP', `QT_INIT', and `QT_BLOCK', that perform
+machine-dependent initialization and blocking, plus code you supply for
+performing the portable operatons. For example, you might write:
+
+ t_create (func, arg)
+ {
+ stk = malloc (STKSIZE);
+ stackbase = QT_SP (stk, STKSIZE);
+ sp = QT_INIT (stakcbase, func, arg);
+ qput (runq, sp);
+ }
+
+Threads block by doing something like:
+
+ t_block()
+ {
+ sp_next = qget (runq);
+ QT_BLOCK (helper, runq, sp_next);
+ // wake up again here
+ }
+
+ // called by QT_BLOCK after the old thread has blocked,
+ // puts the old thread on the queue `onq'.
+ helper (sp_old, onq)
+ {
+ qput (onq, sp_old);
+ }
+
+(Of course) it's actually a bit more complex than that, but the general
+idea is that you write portable code to allocate stacks and enqueue and
+dequeue threads. Than, to get your threads package up and running on a
+different machine, you just reconfigure QuickThreads and recompile, and
+that's it.
+
+The QuickThreads `distribution' includes a sample threads package (look
+at stp.{c,h}) that is written in terms of QuickThreads operations. The
+TR mentioned above explains the simple threads package in detail.
+
+
+
+If you do use QuickThreads, I'd like to hear both about what worked for
+you and what didn't work, problems you had, insights gleaned, etc.
+
+Let me know what you think.
+
+David Keppel <pardo@cs.washington.edu>
diff --git a/ext/systemc/src/sysc/qt/README.MISC b/ext/systemc/src/sysc/qt/README.MISC
new file mode 100644
index 000000000..d10e487cf
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/README.MISC
@@ -0,0 +1,56 @@
+Here's some machine-specific informatin for various systems:
+
+m88k on g88.sim
+
+ .g88init:
+ echo (gdb) target sim\n
+ target sim
+ echo (gdb) ecatch all\n
+ ecatch all
+ echo (gdb) break exit\n
+ break exit
+ % vi Makefile // set CC and AS
+ % setenv MEERKAT /projects/cer/meerkat
+ % set path=($MEERKAT/bin $path)
+ % make run
+ % g88.sim run
+ (g88) run run N // where `N' is the test number
+
+
+m88k on meerkats, cross compile as above (make run)
+
+ Run w/ g88:
+ %g88 run
+ (g88) source /homes/rivers/robertb/.gdbinit
+ (g88) me
+ which does
+ (g88) set $firstchars=6
+ (g88) set $resetonattach=1
+ (g88) attach /dev/pp0
+ then download
+ (g88) dl
+ and run with
+ (g88) continue
+
+ Really the way to run it is:
+ (g88) source
+ (g88) me
+ (g88) win
+ (g88) dead 1
+ (g88) dead 2
+ (g88) dead 3
+ (g88) dl
+ (g88) cont
+
+ To rerun
+ (g88) init
+ (g88) dl
+
+ To run simulated meerkat:
+ (g88) att sim
+ <<then use normal commands>>
+
+ On 4.5 g88:
+ (g88) target sim memsize
+ instead of attatch
+ (g88) ecatch all # catch exception before becomes error
diff --git a/ext/systemc/src/sysc/qt/README.PORT b/ext/systemc/src/sysc/qt/README.PORT
new file mode 100644
index 000000000..d56300923
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/README.PORT
@@ -0,0 +1,112 @@
+Date: Tue, 11 Jan 94 13:23:11 -0800
+From: "pardo@cs.washington.edu" <pardo@meitner.cs.washington.edu>
+
+>[What's needed to get `qt' on an i860-based machine?]
+
+Almost certainly "some assembly required" (pun accepted).
+
+To write a cswap port, you need to understand the context switching
+model. Turn to figure 2 in the QT TR. Here's about what the assembly
+code looks like to implement that:
+
+ qt_cswap:
+ adjust stack pointer
+ save callee-save registers on to old's stack
+ argument register <- old sp
+ sp <- new sp
+ (*helper)(args...)
+ restore callee-save registers from new's stack
+ unadjust stack pointer
+ return
+
+Once more in slow motion:
+
+ - `old' thread calls context switch routine (new, a0, a1, h)
+ - cswap routine saves registers that have useful values
+ - cswap routine switches to new stack
+ - cswap routine calls helper function (*h)(old, a0, a1)
+ - when helper returns, cswap routine restores registers
+ that were saved the last time `new' was suspended
+ - cswap routine returns to whatever `new' routine called the
+ context switch routine
+
+There's a few tricks here. First, how do you start a thread running
+for the very first time? Answer is: fake some stuff on the stack
+so it *looks* like it was called from the middle of some routine.
+When the new thread is restarted, it is treated like any other
+thread. It just so happens that it's never really run before, but
+you can't tell that because the saved state makes it look like like
+it's been run. The return pc is set to point at a little stub of
+assembly code that loads up registers with the right values and
+then calls `only'.
+
+Second, I advise you to forget about varargs routines (at least
+until you get single-arg routines up and running).
+
+Third, on most machines `qt_abort' is the same as `qt_cswap' except
+that it need not save any callee-save registers.
+
+Fourth, `qt_cswap' needs to save and restore any floating-point
+registers that are callee-save (see your processor handbook). On
+some machines, *no* floating-point registers are callee-save, so
+`qt_cswap' is exactly the same as the integer-only cswap routine.
+
+I suggest staring at the MIPS code for a few minutes. It's "mostly"
+generic RISC code, so it gets a lot of the flavor across without
+getting too bogged down in little nitty details.
+
+
+
+Now for a bit more detail: The stack is laid out to hold callee-save
+registers. On many machines, I implemented fp cswap as save fp
+regs, call integer cswap, and when integer cswap returns (when the
+thread wakes up again), restore fp regs.
+
+For thread startup, I figure out some callee-save registers that
+I use to hold parameters to the startup routine (`only'). When
+the thread is being started it doesn't have any saved registers
+that need to be restored, but I go ahead and let the integer context
+switch routine restore some registers then "return" to the stub
+code. The stub code then copies the "callee save" registers to
+argument registers and calls the startup routine. That keeps the
+stub code pretty darn simple.
+
+For each machine I need to know the machine's procedure calling
+convention before I write a port. I figure out how many callee-save
+registers are there and allocate enough stack space for those
+registers. I also figure out how parameters are passed, since I
+will need to call the helper function. On most RISC machines, I
+just need to put the old sp in the 0'th arg register and then call
+indirect through the 3rd arg register; the 1st and 2nd arg registers
+are already set up correctly. Likewise, I don't touch the return
+value register between the helper's return and the context switch
+routine's return.
+
+I have a bunch of macros set up to do the stack initialization.
+The easiest way to debug this stuff is to go ahead and write a C
+routine to do stack initialization. Once you're happy with it you
+can turn it in to a macro.
+
+In general there's a lot of ugly macros, but most of them do simple
+things like return constants, etc. Any time you're looking at it
+and it looks confusing you just need to remember "this is actually
+simple code, the only tricky thing is calling the helper between
+the stack switch and the new thread's register restore."
+
+
+You will almost certainly need to write the assembly code fragment
+that starts a thread. You might be able to do a lot of the context
+switch code with `setjmp' and `longjmp', if they *happen* to have
+the "right" implementation. But getting all the details right (the
+helper can return a value to the new thread's cswap routine caller)
+is probaby trickier than writing code that does the minimum and
+thus doesn't have any extra instructions (or generality) to cause
+problems.
+
+I don't know of any ports besides those included with the source
+code distribution. If you send me a port I will hapily add it to
+the distribution.
+
+Let me know as you have questions and/or comments.
+
+ ;-D on ( Now *that*'s a switch... ) Pardo
diff --git a/ext/systemc/src/sysc/qt/b.h b/ext/systemc/src/sysc/qt/b.h
new file mode 100644
index 000000000..49e587c77
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/b.h
@@ -0,0 +1,11 @@
+#ifndef B_H
+#define B_H "$Header: /Users/acg/CVSROOT/systemc-2.3/src/sysc/qt/b.h,v 1.1.1.1 2006/12/15 20:20:06 acg Exp $"
+
+#include "copyright.h"
+
+extern void b_call_reg (int n);
+extern void b_call_imm (int n);
+extern void b_add (int n);
+extern void b_load (int n);
+
+#endif /* ndef B_H */
diff --git a/ext/systemc/src/sysc/qt/config b/ext/systemc/src/sysc/qt/config
new file mode 100755
index 000000000..35d54647f
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/config
@@ -0,0 +1,392 @@
+#! /bin/sh
+
+# set -x
+
+: ${LN_S:="ln -s"}
+
+# rm -f Makefile Makefile.md README.md qtmd.h qtmdb.s qtmdc.c qtmds.s configuration
+rm -f qtmdc.c qtmds.s configuration
+
+case $1 in
+ axp*)
+ : "DEC AXP"
+ case $1 in
+ axp-osf1*)
+ : "Compile using /bin/cc under OSF 1.x."
+# ${LN_S} md/axp.1.Makefile Makefile.md
+ ;;
+ axp-osf2*)
+ : "Compile using /bin/cc under OSF 2.x."
+# ${LN_S} md/axp.1.Makefile Makefile.md
+ ;;
+ *)
+ : "Compile using GNU CC."
+# ${LN_S} md/axp.Makefile Makefile.md
+ ;;
+ esac
+
+# ${LN_S} md/axp.h qtmd.h
+ ${LN_S} md/axp.c qtmdc.c
+ ${LN_S} md/axp.s qtmds.s
+# ${LN_S} md/axp_b.s qtmdb.s
+# ${LN_S} md/axp.README README.md
+ iter_init=1000000000
+ iter_runone=10000000
+ iter_blockint=10000000
+ iter_blockfloat=10000000
+ iter_vainit0=10000000
+ iter_vainit2=10000000
+ iter_vainit4=10000000
+ iter_vainit8=10000000
+ iter_vastart0=10000000
+ iter_vastart2=10000000
+ iter_vastart4=10000000
+ iter_vastart8=10000000
+ iter_bench_call_reg=10000000
+ iter_bench_call_imm=10000000
+ iter_bench_add=100000000
+ iter_bench_load=100000000
+ ;;
+
+ hppa*)
+ : "HP's PA-RISC 1.1 processors."
+
+ case $1 in
+ hppa-cnx-spp*)
+ : "Convex SPP (PA-RISC 1.1 processors)."
+# ${LN_S} md/hppa-cnx.Makefile Makefile.md
+ ;;
+ *)
+# ${LN_S} md/hppa.Makefile Makefile.md
+ ;;
+ esac
+
+# ${LN_S} md/hppa.h qtmd.h
+# ${LN_S} md/null.c qtmdc.c
+ ${LN_S} md/hppa.s qtmds.s
+# ${LN_S} md/hppa_b.s qtmdb.s
+ iter_init=10000000
+ iter_runone=1000000
+ iter_blockint=1000000
+ iter_blockfloat=1000000
+ iter_vainit0=1000000
+ iter_vainit2=1000000
+ iter_vainit4=1000000
+ iter_vainit8=1000000
+ iter_vastart0=1000000
+ iter_vastart2=1000000
+ iter_vastart4=1000000
+ iter_vastart8=1000000
+ iter_bench_call_reg=10000000
+ iter_bench_call_imm=10000000
+ iter_bench_add=100000000
+ iter_bench_load=100000000
+ ;;
+
+ x86_64*)
+ case $1 in
+ iX86-ss*)
+ : "Assembler comments '//'"
+ sed 's/\/\*/\/\//' < md/i386_64.s > qtmds.s
+ ;;
+
+ *)
+ ${LN_S} md/iX86_64.s qtmds.s
+ ;;
+ esac
+ : "Intel X386 64-bit and compatibles"
+# ${LN_S} md/null.c qtmdc.c
+ iter_init=10000000
+ iter_runone=1000000
+ iter_blockint=1000000
+ iter_blockfloat=1000000
+ iter_vainit0=1000000
+ iter_vainit2=1000000
+ iter_vainit4=1000000
+ iter_vainit8=1000000
+ iter_vastart0=1000000
+ iter_vastart2=1000000
+ iter_vastart4=1000000
+ iter_vastart8=1000000
+ iter_bench_call_reg=1000000
+ iter_bench_call_imm=1000000
+ iter_bench_add=100000000
+ iter_bench_load=10000000
+ ;;
+
+ iX86*)
+ case $1 in
+ iX86-ss*)
+ : "Assembler comments '//'"
+ sed 's/\/\*/\/\//' < md/i386.s > qtmds.s
+# sed 's/\/\*/\/\//' < md/i386_b.s > qtmdb.s
+ ;;
+
+ *)
+ ${LN_S} md/i386.s qtmds.s
+# ${LN_S} md/i386_b.s qtmdb.s
+ ;;
+ esac
+ : "Intel 80386 and compatibles (not '286...)"
+# ${LN_S} md/default.Makefile Makefile.md
+# ${LN_S} md/i386.h qtmd.h
+# ${LN_S} md/null.c qtmdc.c
+# ${LN_S} md/i386.README README.md
+ iter_init=10000000
+ iter_runone=1000000
+ iter_blockint=1000000
+ iter_blockfloat=1000000
+ iter_vainit0=1000000
+ iter_vainit2=1000000
+ iter_vainit4=1000000
+ iter_vainit8=1000000
+ iter_vastart0=1000000
+ iter_vastart2=1000000
+ iter_vastart4=1000000
+ iter_vastart8=1000000
+ iter_bench_call_reg=1000000
+ iter_bench_call_imm=1000000
+ iter_bench_add=100000000
+ iter_bench_load=10000000
+ ;;
+
+
+ m68k)
+ : "Motorola 68000 family -- incomplete!"
+# ${LN_S} md/default.Makefile Makefile.md
+# ${LN_S} md/m68k.h qtmd.h
+# ${LN_S} md/null.c qtmdc.c
+ ${LN_S} md/m68k.s qtmds.s
+# ${LN_S} md/m68k_b.s qtmdb.s
+# ${LN_S} md/null.README README.md
+ ;;
+
+ m88k)
+ : "Motorola 88000 family"
+# ${LN_S} md/m88k.Makefile Makefile.md
+# ${LN_S} md/m88k.h qtmd.h
+ ${LN_S} md/m88k.c qtmdc.c
+ ${LN_S} md/m88k.s qtmds.s
+# ${LN_S} md/m88k_b.s qtmdb.s
+# ${LN_S} md/null.README README.md
+ iter_init=1000000
+ iter_runone=100000
+ iter_blockint=100000
+ iter_blockfloat=100000
+ iter_vainit0=100000
+ iter_vainit2=100000
+ iter_vainit4=100000
+ iter_vainit8=100000
+ iter_vastart0=100000
+ iter_vastart2=100000
+ iter_vastart4=100000
+ iter_vastart8=100000
+ iter_bench_call_reg=100000000
+ iter_bench_call_imm=100000000
+ iter_bench_add=1000000000
+ iter_bench_load=100000000
+ ;;
+
+ mips*)
+ : "MIPS R2000 and R3000."
+
+ case $1 in
+ mips-irix5*)
+ : "Silicon Graphics Irix with dynamic linking"
+ : "Use mips for irix4."
+ ${LN_S} md/mips-irix5.s qtmds.s
+ ;;
+ *)
+ ${LN_S} md/mips.s qtmds.s
+ ;;
+ esac
+
+# ${LN_S} md/default.Makefile Makefile.md
+# ${LN_S} md/mips.h qtmd.h
+# ${LN_S} md/null.c qtmdc.c
+# ${LN_S} md/mips_b.s qtmdb.s
+# ${LN_S} md/null.README README.md
+ iter_init=10000000
+ iter_runone=10000000
+ iter_blockint=10000000
+ iter_blockfloat=10000000
+ iter_vainit0=1000000
+ iter_vainit2=1000000
+ iter_vainit4=1000000
+ iter_vainit8=1000000
+ iter_vastart0=1000000
+ iter_vastart2=1000000
+ iter_vastart4=1000000
+ iter_vastart8=1000000
+ iter_bench_call_reg=100000000
+ iter_bench_call_imm=100000000
+ iter_bench_add=1000000000
+ iter_bench_load=100000000
+ ;;
+
+ sparc*)
+ : "SPARC processors"
+ case $1 in
+ sparc-os2*)
+ sed 's/_qt_/qt_/' md/sparc.s > qtmds.s
+# sed 's/_b_/b_/' md/sparc_b.s > qtmdb.s
+# ${LN_S} md/solaris.README README.md
+ ;;
+ *)
+ ${LN_S} md/sparc.s qtmds.s
+# ${LN_S} md/sparc_b.s qtmdb.s
+# ${LN_S} md/null.README README.md
+ ;;
+ esac
+
+ ${LN_S} md/default.Makefile Makefile.md
+# ${LN_S} md/sparc.h qtmd.h
+# ${LN_S} md/null.c qtmdc.c
+ iter_init=10000000
+ iter_runone=1000000
+ iter_blockint=1000000
+ iter_blockfloat=1000000
+ iter_vainit0=1000000
+ iter_vainit2=1000000
+ iter_vainit4=1000000
+ iter_vainit8=1000000
+ iter_vastart0=1000000
+ iter_vastart2=1000000
+ iter_vastart4=1000000
+ iter_vastart8=1000000
+ iter_bench_call_reg=10000000
+ iter_bench_call_imm=10000000
+ iter_bench_add=100000000
+ iter_bench_load=100000000
+ ;;
+
+ vax*)
+ : "DEC VAX processors."
+# ${LN_S} md/default.Makefile Makefile.md
+# ${LN_S} md/vax.h qtmd.h
+# ${LN_S} md/null.c qtmdc.c
+ ${LN_S} md/vax.s qtmds.s
+# ${LN_S} md/vax_b.s qtmdb.s
+# ${LN_S} md/null.README README.md
+ iter_init=1000000
+ iter_runone=100000
+ iter_blockint=100000
+ iter_blockfloat=100000
+ iter_vainit0=100000
+ iter_vainit2=100000
+ iter_vainit4=100000
+ iter_vainit8=100000
+ iter_vastart0=100000
+ iter_vastart2=100000
+ iter_vastart4=100000
+ iter_vastart8=100000
+ iter_bench_call_reg=10000000
+ iter_bench_call_imm=10000000
+ iter_bench_add=10000000
+ iter_bench_load=1000000
+ ;;
+
+ ksr1)
+ : "Kendall Square Research model KSR-1."
+ : "Varargs is not currently supported."
+# ${LN_S} md/ksr1.Makefile Makefile.md
+# ${LN_S} md/ksr1.h qtmd.h
+# ${LN_S} md/null.c qtmdc.c
+ ${LN_S} md/ksr1.s qtmds.s
+# ${LN_S} md/ksr1_b.s qtmdb.s
+# ${LN_S} md/null.README README.md
+ iter_init=1000000
+ iter_runone=100000
+ iter_blockint=100000
+ iter_blockfloat=100000
+ iter_vainit0=100000
+ iter_vainit2=100000
+ iter_vainit4=100000
+ iter_vainit8=100000
+ iter_vastart0=100000
+ iter_vastart2=100000
+ iter_vastart4=100000
+ iter_vastart8=100000
+ iter_bench_call_reg=10000000
+ iter_bench_call_imm=10000000
+ iter_bench_add=10000000
+ iter_bench_load=1000000
+ ;;
+
+ powerpc*)
+ : "PowerPC IBM/Motorola processors."
+
+ case $1 in
+ powerpc-apple-macosx*)
+ : "PowerPC using Mach Application Binary Interface"
+ : "NOTICE: Darwin assembler syntax is used:"
+ : " (i.e. registers are named rx not %rx)"
+ ${LN_S} md/default.Makefile Makefile.md
+# ${LN_S} md/powerpc_mach.h qtmd.h
+ ${LN_S} md/powerpc_mach.s qtmds.s
+ ;;
+ powerpc-linux*)
+ : "PowerPC using System V Application Binary Interface"
+ : " (e.g. LinuxPPC)"
+ : "Use powerpc-darwin for MacOS X and other systems based on Mac
+h ABI"
+# ${LN_S} md/powerpc_sys5.h qtmd.h
+ ${LN_S} md/powerpc_sys5.s qtmds.s
+ ;;
+ *)
+ echo "Unknown configuration"
+ echo "See md/powerpc.README for documentation"
+ echo "Use powerpc-darwin for MacOS X and other systems based on
+Mach ABI"
+ echo "Use powerpc-linux for Linux and other systems based on Sys
+tem V ABI"
+ exit 1
+ ;;
+
+ esac
+
+ ${LN_S} md/powerpc.c qtmdc.c
+ ${LN_S} md/powerpc.README README.md
+ ;;
+
+
+ pthreads*)
+ : Posix thread support rather than Quick threads.
+# ${LN_S} md/hppa.h qtmd.h
+# ${LN_S} md/null.c qtmdc.c
+# ${LN_S} md/null.s qtmds.s
+# ${LN_S} md/hppa_b.s qtmdb.s
+# cp md/pthreads.Makefile Makefile
+ exit 0
+ ;;
+
+ clean)
+ : Deconfigure
+ exit 0
+ ;;
+
+ *)
+ echo "Unknown configuration"
+ exit 1
+ ;;
+esac
+
+# cat Makefile.md Makefile.base > Makefile
+
+echo set config_machine=$1 >> configuration
+echo set config_init=$iter_init >> configuration
+echo set config_runone=$iter_runone >> configuration
+echo set config_blockint=$iter_blockint >> configuration
+echo set config_blockfloat=$iter_blockfloat >> configuration
+echo set config_vainit0=$iter_vainit0 >> configuration
+echo set config_vainit2=$iter_vainit2 >> configuration
+echo set config_vainit4=$iter_vainit4 >> configuration
+echo set config_vainit8=$iter_vainit8 >> configuration
+echo set config_vastart0=$iter_vastart0 >> configuration
+echo set config_vastart2=$iter_vastart2 >> configuration
+echo set config_vastart4=$iter_vastart4 >> configuration
+echo set config_vastart8=$iter_vastart8 >> configuration
+echo set config_bcall_reg=$iter_bench_call_reg >> configuration
+echo set config_bcall_imm=$iter_bench_call_imm >> configuration
+echo set config_b_add=$iter_bench_add >> configuration
+echo set config_b_load=$iter_bench_load >> configuration
diff --git a/ext/systemc/src/sysc/qt/copyright.h b/ext/systemc/src/sysc/qt/copyright.h
new file mode 100644
index 000000000..8a2361f9e
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/copyright.h
@@ -0,0 +1,12 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
diff --git a/ext/systemc/src/sysc/qt/md/axp.1.Makefile b/ext/systemc/src/sysc/qt/md/axp.1.Makefile
new file mode 100644
index 000000000..86ccd8f42
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/axp.1.Makefile
@@ -0,0 +1,5 @@
+
+#
+# Compiling for the DEC AXP (alpha) with GNU CC or version 1.x of OSF.
+#
+CC = cc -std1 -D__AXP__ -D__OSF1__
diff --git a/ext/systemc/src/sysc/qt/md/axp.2.Makefile b/ext/systemc/src/sysc/qt/md/axp.2.Makefile
new file mode 100644
index 000000000..268636fc9
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/axp.2.Makefile
@@ -0,0 +1,5 @@
+
+#
+# Compiling for the DEC AXP (alpha) with GNU CC or version 2.x of OSF.
+#
+CC = cc -std1 -D__AXP__ -D__OSF2__
diff --git a/ext/systemc/src/sysc/qt/md/axp.Makefile b/ext/systemc/src/sysc/qt/md/axp.Makefile
new file mode 100644
index 000000000..4e6d74da4
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/axp.Makefile
@@ -0,0 +1,5 @@
+
+#
+# GNU CC
+#
+CC = gcc -D__AXP__
diff --git a/ext/systemc/src/sysc/qt/md/axp.README b/ext/systemc/src/sysc/qt/md/axp.README
new file mode 100644
index 000000000..b6a705c07
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/axp.README
@@ -0,0 +1,10 @@
+The handling of varargs is platform-dependent. Assar Westerlund
+stared at the problem for a while and deduces the following table:
+
+vers / compiler cc gcc
+----------------------------------------------------------------------
+1.3 a0, offset __base, __offset
+2.0 _a0, _offset __base, __offset
+
+The current code should handle both cc and gcc versions, provided
+you configure for the correct compiler.
diff --git a/ext/systemc/src/sysc/qt/md/axp.c b/ext/systemc/src/sysc/qt/md/axp.c
new file mode 100644
index 000000000..268612993
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/axp.c
@@ -0,0 +1,133 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+#include <stdarg.h>
+#include "qt.h"
+
+
+/* Varargs is harder on the AXP. Parameters are saved on the stack as
+ something like (stack grows down to low memory; low at bottom of
+ picture):
+
+ | :
+ | arg6
+ +---
+ | iarg5
+ | :
+ | iarg3 <-- va_list._a0 + va_list._offset
+ | :
+ | iarg0 <-- va_list._a0
+ +---
+ | farg5
+ | :
+ | farg0
+ +---
+
+ When some of the arguments have known type, there is no need to
+ save all of them in the struct. So, for example, if the routine is
+ called
+
+ zork (int a0, float a1, int a2, ...)
+ {
+ va_list ap;
+ va_start (ap, a2);
+ qt_vargs (... &ap ...);
+ }
+
+ then offset is set to 3 * 8 (8 === sizeof machine word) = 24.
+
+ What this means for us is that the user's routine needs to be
+ called with an arg list where some of the words in the `any type'
+ parameter list have to be split and moved up in to the int/fp
+ region.
+
+ Ways in which this can fail:
+ - The user might not know the size of the pushed arguments anyway.
+ - Structures have funny promotion rules.
+ - Probably lots of other things.
+
+ All in all, we never promised varargs would work reliably. */
+
+
+
+#define QUICKTHREADS_VADJ(sp) (((char *)sp) - QUICKTHREADS_VSTKBASE)
+
+#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \
+ ((qt_t *)(((char *)(sp)) - 6*2*8 - QUICKTHREADS_STKROUNDUP(vabytes)))
+
+extern void qt_vstart(void);
+#define QUICKTHREADS_VARGS_MD1(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_R26, qt_vstart))
+
+
+/* Different machines use different implementations for varargs.
+ Unfortunately, the code below ``looks in to'' the varargs
+ structure, `va_list', and thus depends on the conventions.
+ The following #defines try to deal with it but don't catch
+ everything. */
+
+#ifdef __GNUC__
+#define _a0 __base
+#define _offset __offset
+#else
+#ifdef __OSF1__
+#define _a0 a0
+#define _offset offset
+#endif
+#endif /* def __GNUC__ */
+
+
+ struct qt_t *
+qt_vargs (struct qt_t *qsp, int nbytes, struct va_list *vargs,
+ void *pt, qt_function_t *startup,
+ qt_function_t *vuserf, qt_function_t *cleanup)
+{
+ va_list ap;
+ int i;
+ int max; /* Maximum *words* of args to copy. */
+ int tmove; /* *Words* of args moved typed->typed. */
+ qt_word_t *sp;
+
+ ap = *(va_list *)vargs;
+ qsp = QUICKTHREADS_VARGS_MD0 (qsp, nbytes);
+ sp = (qt_word_t *)qsp;
+
+ tmove = 6 - ap._offset/sizeof(qt_word_t);
+
+ /* Copy from one typed area to the other. */
+ for (i=0; i<tmove; ++i) {
+ /* Integer args: */
+ sp[i+6] = ((qt_word_t *)(ap._a0 + ap._offset))[i];
+ /* Fp args: */
+ sp[i] = ((qt_word_t *)(ap._a0 + ap._offset))[i-6];
+ }
+
+ max = nbytes/sizeof(qt_word_t);
+
+ /* Copy from the untyped area to the typed area. Split each arg.
+ in to integer and floating-point save areas. */
+ for (; i<6 && i<max; ++i) {
+ sp[i] = sp[i+6] = ((qt_word_t *)(ap._a0 + ap._offset))[i];
+ }
+
+ /* Copy from the untyped area to the other untyped area. */
+ for (; i<max; ++i) {
+ sp[i+6] = ((qt_word_t *)(ap._a0 + ap._offset))[i];
+ }
+
+ QUICKTHREADS_VARGS_MD1 (QUICKTHREADS_VADJ(sp));
+ QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VARGT_INDEX, pt);
+ QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VSTARTUP_INDEX, startup);
+ QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VUSERF_INDEX, vuserf);
+ QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VCLEANUP_INDEX, cleanup);
+ return ((qt_t *)QUICKTHREADS_VADJ(sp));
+}
diff --git a/ext/systemc/src/sysc/qt/md/axp.h b/ext/systemc/src/sysc/qt/md/axp.h
new file mode 100644
index 000000000..3aac9ff1d
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/axp.h
@@ -0,0 +1,160 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+#ifndef QUICKTHREADS_AXP_H
+#define QUICKTHREADS_AXP_H
+
+#define QUICKTHREADS_GROW_DOWN
+
+typedef unsigned long qt_word_t;
+
+
+/* Stack layout on the Alpha:
+
+ Integer:
+
+ Caller-save: r0..r8, r22..r25, r27..r29
+ argument/caller-save: r16..r21
+ callee-save: r9..r15
+ return pc *callee-save*: r26
+ stack pointer: r30
+ zero: r31
+
+ Floating-point:
+
+ Caller-save: f0..f1, f10..f15
+ argument/caller-save: f16..f21, f22..f30
+ callee-save: f2..f9
+ zero: f31
+
+ Non-varargs:
+
+ +---
+ | padding
+ | f9
+ | f8
+ | f7
+ | f6
+ | f5
+ | f4
+ | f3
+ | f2
+ | r26
+ +---
+ | padding
+ | r29
+ | r15
+ | r14
+ | r13
+ | r12 on startup === `only'
+ | r11 on startup === `userf'
+ | r10 on startup === `qt'
+ | r9 on startup === `qu'
+ | r26 on startup === qt_start <--- qt.sp
+ +---
+
+ Conventions for varargs startup:
+
+ | :
+ | arg6
+ | iarg5
+ | :
+ | iarg0
+ | farg5
+ | :
+ | farg0
+ +---
+ | padding
+ | r29
+ | r15
+ | r14
+ | r13
+ | r12 on startup === `startup'
+ | r11 on startup === `vuserf'
+ | r10 on startup === `cleanup'
+ | r9 on startup === `qt'
+ | r26 on startup === qt_vstart <--- qt.sp
+ +---
+
+ Note: this is a pretty cheap/sleazy way to get things going,
+ but ``there must be a better way.'' For instance, some varargs
+ parameters could be loaded in to integer registers, or the return
+ address could be stored on top of the stack. */
+
+
+/* Stack must be 16-byte aligned. */
+#define QUICKTHREADS_STKALIGN (16)
+
+/* How much space is allocated to hold all the crud for
+ initialization: 7 registers times 8 bytes/register. */
+
+#define QUICKTHREADS_STKBASE (10 * 8)
+#define QUICKTHREADS_VSTKBASE QUICKTHREADS_STKBASE
+
+
+/* Offsets of various registers. */
+#define QUICKTHREADS_R26 0
+#define QUICKTHREADS_R9 1
+#define QUICKTHREADS_R10 2
+#define QUICKTHREADS_R11 3
+#define QUICKTHREADS_R12 4
+
+
+/* When a never-before-run thread is restored, the return pc points
+ to a fragment of code that starts the thread running. For
+ non-vargs functions, it just calls the client's `only' function.
+ For varargs functions, it calls the startup, user, and cleanup
+ functions.
+
+ The varargs startup routine always reads 12 8-byte arguments from
+ the stack. If fewer argumets were pushed, the startup routine
+ would read off the top of the stack. To prevent errors we always
+ allocate enough space. When there are fewer args, the preallocated
+ words are simply wasted. */
+
+extern void qt_start(void);
+#define QUICKTHREADS_ARGS_MD(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_R26, qt_start))
+
+
+/* The AXP uses a struct for `va_list', so pass a pointer to the
+ struct. This may break some uses of `QUICKTHREADS_VARGS', but then we never
+ claimed it was totally portable. */
+
+typedef void (qt_function_t)(void);
+
+struct qt_t;
+struct va_list;
+extern struct qt_t *qt_vargs (struct qt_t *sp, int nbytes,
+ struct va_list *vargs, void *pt,
+ qt_function_t *startup,
+ qt_function_t *vuserf,
+ qt_function_t *cleanup);
+
+#define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \
+ (qt_vargs (sp, nbytes, (struct va_list *)(&(vargs)), pt, \
+ (qt_function_t *) startup, (qt_function_t *)vuserf, \
+ (qt_function_t *)cleanup));
+
+
+/* The *index* (positive offset) of where to put each value. */
+#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_R12)
+#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_R11)
+#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_R10)
+#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_R9)
+
+#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_R10)
+#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_R11)
+#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_R12)
+#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_R9)
+
+#endif /* ndef QUICKTHREADS_AXP_H */
diff --git a/ext/systemc/src/sysc/qt/md/axp.s b/ext/systemc/src/sysc/qt/md/axp.s
new file mode 100644
index 000000000..a84aab2cc
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/axp.s
@@ -0,0 +1,160 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+/* axp.s -- assembly support. */
+
+ .text
+ .align 4
+ .file 2 "axp.s"
+
+ .globl qt_block
+ .globl qt_blocki
+ .globl qt_abort
+ .globl qt_start
+ .globl qt_vstart
+
+ /*
+ ** $16: ptr to function to call once curr is suspended
+ ** and control is on r19's stack.
+ ** $17: 1'th arg to (*$16)(...).
+ ** $18: 2'th arg to (*$16)(...).
+ ** $19: sp of thread to resume.
+ **
+ ** The helper routine returns a value that is passed on as the
+ ** return value from the blocking routine. Since we don't
+ ** touch r0 between the helper's return and the end of
+ ** function, we get this behavior for free.
+ */
+
+ .ent qt_blocki
+qt_blocki:
+ subq $30,80, $30 /* Allocate save area. */
+ stq $26, 0($30) /* Save registers. */
+ stq $9, 8($30)
+ stq $10,16($30)
+ stq $11,24($30)
+ stq $12,32($30)
+ stq $13,40($30)
+ stq $14,48($30)
+ stq $15,56($30)
+ stq $29,64($30)
+ .end qt_blocki
+ .ent qt_abort
+qt_abort:
+ addq $16,$31, $27 /* Put argument function in PV. */
+ addq $30,$31, $16 /* Save stack ptr in outgoing arg. */
+ addq $19,$31, $30 /* Set new stack pointer. */
+ jsr $26,($27),0 /* Call helper function. */
+
+ ldq $26, 0($30) /* Restore registers. */
+ ldq $9, 8($30)
+ ldq $10,16($30)
+ ldq $11,24($30)
+ ldq $12,32($30)
+ ldq $13,40($30)
+ ldq $14,48($30)
+ ldq $15,56($30)
+ ldq $29,64($30)
+
+ addq $30,80, $30 /* Deallocate save area. */
+ ret $31,($26),1 /* Return, predict===RET. */
+ .end qt_abort
+
+
+ /*
+ ** Non-varargs thread startup.
+ */
+ .ent qt_start
+qt_start:
+ addq $9,$31, $16 /* Load up `qu'. */
+ addq $10,$31, $17 /* ... user function's `pt'. */
+ addq $11,$31, $18 /* ... user function's `userf'. */
+ addq $12,$31, $27 /* ... set procedure value to `only'. */
+ jsr $26,($27),0 /* Call `only'. */
+
+ jsr $26,qt_error /* `only' erroniously returned. */
+ .end qt_start
+
+
+ .ent qt_vstart:
+qt_vstart:
+ /* Call startup function. */
+ addq $9,$31, $16 /* Arg0 to `startup'. */
+ addq $12,$31, $27 /* Set procedure value. */
+ jsr $26,($27),0 /* Call `startup'. */
+
+ /* Call user function. */
+ ldt $f16, 0($30) /* Load fp arg regs. */
+ ldt $f17, 8($30)
+ ldt $f18,16($30)
+ ldt $f19,24($30)
+ ldt $f20,32($30)
+ ldt $f21,40($30)
+ ldq $16,48($30) /* And integer arg regs. */
+ ldq $17,56($30)
+ ldq $18,64($30)
+ ldq $19,72($30)
+ ldq $20,80($30)
+ ldq $21,88($30)
+ addq $30,96 $30 /* Pop 6*2*8 saved arg regs. */
+ addq $11,$31, $27 /* Set procedure value. */
+ jsr $26,($27),0 /* Call `vuserf'. */
+
+ /* Call cleanup. */
+ addq $9,$31, $16 /* Arg0 to `cleanup'. */
+ addq $0,$31, $17 /* Users's return value is arg1. */
+ addq $10,$31, $27 /* Set procedure value. */
+ jsr $26,($27),0 /* Call `cleanup'. */
+
+ jsr $26,qt_error /* Cleanup erroniously returned. */
+ .end qt_start
+
+
+ /*
+ ** Save calle-save floating-point regs $f2..$f9.
+ ** Also save return pc from whomever called us.
+ **
+ ** Return value from `qt_block' is the same as the return from
+ ** `qt_blocki'. We get that for free since we don't touch $0
+ ** between the return from `qt_blocki' and the return from
+ ** `qt_block'.
+ */
+ .ent qt_block
+qt_block:
+ subq $30,80, $30 /* Allocate a save space. */
+ stq $26, 0($30) /* Save registers. */
+ stt $f2, 8($30)
+ stt $f3,16($30)
+ stt $f4,24($30)
+ stt $f5,32($30)
+ stt $f6,40($30)
+ stt $f7,48($30)
+ stt $f8,56($30)
+ stt $f9,64($30)
+
+ jsr $26,qt_blocki /* Call helper. */
+ /* .. who will also restore $gp. */
+
+ ldq $26, 0($30) /* restore registers. */
+ ldt $f2, 8($30)
+ ldt $f3,16($30)
+ ldt $f4,24($30)
+ ldt $f5,32($30)
+ ldt $f6,40($30)
+ ldt $f7,48($30)
+ ldt $f8,56($30)
+ ldt $f9,64($30)
+
+ addq $30,80, $30 /* Deallcate save space. */
+ ret $31,($26),1 /* Return, predict===RET. */
+ .end qt_block
diff --git a/ext/systemc/src/sysc/qt/md/axp_b.s b/ext/systemc/src/sysc/qt/md/axp_b.s
new file mode 100644
index 000000000..60be726ff
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/axp_b.s
@@ -0,0 +1,111 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+ .text
+ .globl b_call_reg
+ .globl b_call_imm
+ .globl b_add
+ .globl b_load
+
+ .ent b_null
+b_null:
+ ret $31,($18),1
+ .end b_null
+
+ .ent b_call_reg
+b_call_reg:
+ lda $27,b_null
+$L0:
+ jsr $18,($27)
+ jsr $18,($27)
+ jsr $18,($27)
+ jsr $18,($27)
+ jsr $18,($27)
+
+ jsr $18,($27)
+ jsr $18,($27)
+ jsr $18,($27)
+ jsr $18,($27)
+ jsr $18,($27)
+
+ subq $16,1,$16
+ bgt $16,$L0
+
+ ret $31,($26),1
+ .end
+
+
+ .ent b_call_imm
+b_call_imm:
+$L1:
+ jsr $18,b_null
+ jsr $18,b_null
+ jsr $18,b_null
+ jsr $18,b_null
+ jsr $18,b_null
+
+ jsr $18,b_null
+ jsr $18,b_null
+ jsr $18,b_null
+ jsr $18,b_null
+ jsr $18,b_null
+
+ subq $16,1,$16
+ bgt $16,$L1
+
+ ret $31,($26),1
+ .end
+
+
+ .ent b_add
+b_add:
+$L2:
+ addq $31,$31,$31
+ addq $31,$31,$31
+ addq $31,$31,$31
+ addq $31,$31,$31
+ addq $31,$31,$31
+
+ addq $31,$31,$31
+ addq $31,$31,$31
+ addq $31,$31,$31
+ addq $31,$31,$31
+ addq $31,$31,$31
+
+ subq $16,1,$16
+ bgt $16,$L2
+
+ ret $31,($26),1
+ .end
+
+
+ .ent b_load
+b_load:
+$L3:
+ ldq $31,0($30)
+ ldq $31,8($30)
+ ldq $31,16($30)
+ ldq $31,24($30)
+ ldq $31,32($30)
+
+ ldq $31,0($30)
+ ldq $31,8($30)
+ ldq $31,16($30)
+ ldq $31,24($30)
+ ldq $31,32($30)
+
+ subq $16,1,$16
+ bgt $16,$L3
+
+ ret $31,($26),1
+ .end
diff --git a/ext/systemc/src/sysc/qt/md/default.Makefile b/ext/systemc/src/sysc/qt/md/default.Makefile
new file mode 100644
index 000000000..2f3ded151
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/default.Makefile
@@ -0,0 +1,8 @@
+
+#
+# `Normal' configuration.
+#
+CC = gcc -ansi -Wall -pedantic
+
+.o.s:
+ as -o $@ $<
diff --git a/ext/systemc/src/sysc/qt/md/hppa-cnx.Makefile b/ext/systemc/src/sysc/qt/md/hppa-cnx.Makefile
new file mode 100644
index 000000000..bff257d9f
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/hppa-cnx.Makefile
@@ -0,0 +1,9 @@
+# This file (cnx_spp.Makefile) is part of the port of QuickThreads for
+# PA-RISC 1.1 architecture on a Convex SPP. This file is a machine dependent
+# makefile for QuickThreads. It was written in 1994 by Uwe Reder
+# (`uereder@cip.informatik.uni-erlangen.de') for the Operating Systems
+# Department (IMMD4) at the University of Erlangen/Nuernberg Germany.
+
+# `Normal' configuration.
+
+CC = /usr/convex/bin/cc
diff --git a/ext/systemc/src/sysc/qt/md/hppa.Makefile b/ext/systemc/src/sysc/qt/md/hppa.Makefile
new file mode 100644
index 000000000..bf770ae3b
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/hppa.Makefile
@@ -0,0 +1,12 @@
+# This file (pa-risc.Makefile) is part of the port of QuickThreads for
+# PA-RISC 1.1 architecture. This file is a machine dependent makefile
+# for QuickThreads. It was written in 1994 by Uwe Reder
+# (`uereder@cip.informatik.uni-erlangen.de') for the Operating Systems
+# Department (IMMD4) at the University of Erlangen/Nuernberg Germany.
+
+# `Normal' configuration.
+
+CC = cc -Aa
+
+.s.o:
+ /usr/ccs/bin/as -o $@ $<
diff --git a/ext/systemc/src/sysc/qt/md/hppa.h b/ext/systemc/src/sysc/qt/md/hppa.h
new file mode 100644
index 000000000..fdb9cef93
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/hppa.h
@@ -0,0 +1,196 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+/*
+ * This file (pa-risc.h) is part of the port of QuickThreads for the
+ * PA-RISC 1.1 architecture. This file is a machine dependent header
+ * file. It was written in 1994 by Uwe Reder
+ * (`uereder@cip.informatik.uni-erlangen.de') for the Operating Systems
+ * Department (IMMD4) at the University of Erlangen/Nuernberg Germany.
+ */
+
+
+#ifndef QUICKTHREADS_PA_RISC_H
+#define QUICKTHREADS_PA_RISC_H
+
+#if 0
+#include <qt.h>
+#endif
+
+/* size of an integer-register (32 bit) */
+typedef unsigned long qt_word_t;
+
+/* PA-RISC's stack grows up */
+#define QUICKTHREADS_GROW_UP
+
+/* Stack layout on PA-RISC according to PA-RISC Procedure Calling Conventions:
+
+ Callee-save registers are: gr3-gr18, fr12-fr21.
+ Also save gr2, return pointer.
+
+ +---
+ | fr12 Each floating register is a double word (8 bytes).
+ | fr13 Floating registers are only saved if `qt_block' is
+ | fr14 called, in which case it saves the floating-point
+ | fr15 registers then calls `qt_blocki' to save the integer
+ | fr16 registers.
+ | fr17
+ | fr18
+ | fr19
+ | fr20
+ | fr21
+ | <arg word 3> fixed arguments (must be allocated; may remain unused)
+ | <arg word 2>
+ | <arg word 1>
+ | <arg word 0>
+ | <LPT> frame marker
+ | <LPT'>
+ | <RP'>
+ | <Current RP>
+ | <Static Link>
+ | <Clean Up>
+ | <RP''>
+ | <Previous SP>
+ +---
+ | gr3 word each (4 bytes)
+ | gr4
+ | gr5
+ | gr6
+ | gr7
+ | gr8
+ | gr9
+ | gr10
+ | gr11
+ | gr12
+ | gr13
+ | gr14
+ | gr15
+ | gr16
+ | gr17
+ | gr18
+ | <16 bytes filled in (sp has to be 64-bytes aligned)>
+ | <arg word 3> fixed arguments (must be allocated; may remain unused)
+ | <arg word 2>
+ | <arg word 1>
+ | <arg word 0>
+ | <LPT> frame marker
+ | <LPT'>
+ | <RP'>
+ | <Current RP>
+ | <Static Link>
+ | <Clean Up>
+ | <RP''>
+ | <Previous SP>
+ +--- <--- sp
+*/
+
+/* When a never-before-run thread is restored, the return pc points
+ to a fragment of code that starts the thread running. For
+ non-vargs functions, it just calls the client's `only' function.
+ For varargs functions, it calls the startup, user, and cleanup
+ functions. */
+
+/* Note: Procedue Labels on PA-RISC
+
+ <--2--><-------28---------><1-><1->
+ -----------------------------------
+ | SID | Adress Part | L | X |
+ -----------------------------------
+
+ On HP-UX the L field is used to flag wheather the procedure
+ label (plabel) is a pointer to an LT entry or to the entry point
+ of the procedure (PA-RISC Procedure Calling Conventions Reference
+ Manual, 5.3.2 Procedure Labels and Dynamic Calls). */
+
+#define QUICKTHREADS_PA_RISC_READ_PLABEL(plabel) \
+ ( (((int)plabel) & 2) ? \
+ ( (*((int *)(((int)plabel) & 0xfffffffc)))) : ((int)plabel) )
+
+/* Stack must be 64 bytes aligned. */
+#define QUICKTHREADS_STKALIGN (64)
+
+/* Internal helper for putting stuff on stack (negative index!). */
+#define QUICKTHREADS_SPUT(top, at, val) \
+ (((qt_word_t *)(top))[-(at)] = (qt_word_t)(val))
+
+/* Offsets of various registers which are modified on the stack.
+ rp (return-pointer) has to be stored in the frame-marker-area
+ of the "older" stack-segment. */
+
+#define QUICKTHREADS_crp (12+4+16+5)
+#define QUICKTHREADS_15 (12+4+4)
+#define QUICKTHREADS_16 (12+4+3)
+#define QUICKTHREADS_17 (12+4+2)
+#define QUICKTHREADS_18 (12+4+1)
+
+
+/** This stuff is for NON-VARARGS. **/
+
+/* Stack looks like this (2 stack frames):
+
+ <--- 64-bytes aligned --><------- 64-bytes aligned ------------>
+ | || |
+ <--16--><------48-------><----16*4-----><--16-><------48------->
+ || | || | | ||
+ ||filler|arg|frame-marker||register-save|filler|arg|frame-marker||
+ ------------------------------------------------------------------
+ */
+
+#define QUICKTHREADS_STKBASE (16+48+(16*sizeof(qt_word_t))+16+48)
+
+/* The index, relative to sp, of where to put each value. */
+#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_15)
+#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_16)
+#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_17)
+#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_18)
+
+extern void qt_start(void);
+#define QUICKTHREADS_ARGS_MD(sp) \
+ (QUICKTHREADS_SPUT (sp, QUICKTHREADS_crp, QUICKTHREADS_PA_RISC_READ_PLABEL(qt_start)))
+
+
+/** This is for VARARGS. **/
+
+#define QUICKTHREADS_VARGS_DEFAULT
+
+/* Stack looks like this (2 stack frames):
+
+ <------ 64-bytes aligned -------><--------- 64-bytes aligned ---------->
+ | || |
+ <---?--><--?---><16><----32-----><----16*4-----><-16--><16><----32----->
+ || | | | || | | | ||
+ ||filler|varargs|arg|frame-marker||register-save|filler|arg|frame-marker||
+ --------------------------------------------------------------------------
+ */
+
+/* Sp is moved to the end of the first stack frame. */
+#define QUICKTHREADS_VARGS_MD0(sp, vasize) \
+ ((qt_t *)(((char *)sp) + QUICKTHREADS_STKROUNDUP(vasize + 4*4 + 32)))
+
+/* To reach the arguments from the end of the first stack frame use 32
+ as a negative adjustment. */
+#define QUICKTHREADS_VARGS_ADJUST(sp) ((qt_t *)(((char *)sp) - 32))
+
+/* Offset to reach the end of the second stack frame. */
+#define QUICKTHREADS_VSTKBASE ((16*sizeof(qt_word_t)) + 16 + 4*4 + 32)
+
+extern void qt_vstart(void);
+#define QUICKTHREADS_VARGS_MD1(sp) \
+ (QUICKTHREADS_SPUT (sp, QUICKTHREADS_crp, QUICKTHREADS_PA_RISC_READ_PLABEL(qt_vstart)))
+
+#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_15)
+#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_16)
+#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_17)
+#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_18)
+
+#endif /* ndef QUICKTHREADS_PA_RISC_H */
diff --git a/ext/systemc/src/sysc/qt/md/hppa.s b/ext/systemc/src/sysc/qt/md/hppa.s
new file mode 100644
index 000000000..84d8e875b
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/hppa.s
@@ -0,0 +1,237 @@
+; pa-risc.s -- assembly support.
+
+; QuickThreads -- Threads-building toolkit.
+; Copyright (c) 1993 by David Keppel
+;
+; Permission to use, copy, modify and distribute this software and
+; its documentation for any purpose and without fee is hereby
+; granted, provided that the above copyright notice and this notice
+; appear in all copies. This software is provided as a
+; proof-of-concept and for demonstration purposes; there is no
+; representation about the suitability of this software for any
+; purpose.
+
+; This file (pa-risc.s) is part of the port of QuickThreads for
+; PA-RISC 1.1 architecture. This file implements context switches
+; and thread startup. It was written in 1994 by Uwe Reder
+; (`uereder@cip.informatik.uni-erlangen.de') for the Operating
+; Systems Department (IMMD4) at the University of Erlangen/Nuernberg
+; Germany.
+
+
+; Callee saves general registers gr3..gr18,
+; floating-point registers fr12..fr21.
+
+ .CODE
+
+ .IMPORT $$dyncall, MILLICODE
+ .IMPORT qt_error, CODE
+
+ .EXPORT qt_blocki, ENTRY
+ .EXPORT qt_block, ENTRY
+ .EXPORT qt_abort, ENTRY
+ .EXPORT qt_start, ENTRY
+ .EXPORT qt_vstart, ENTRY
+
+
+; arg0: ptr to function (helper) to call once curr is suspended
+; and control is on arg3's stack.
+; arg1: 1'th arg to *arg0.
+; arg2: 2'th arg to *arg0.
+; arg3: sp of new thread.
+
+qt_blocki
+ .PROC
+ .CALLINFO CALLER, FRAME=0, SAVE_RP, ENTRY_GR=18
+ .ENTRY
+
+ stw %rp,-20(%sp) ; save rp to old frame-marker
+
+ stwm %r3,128(%sp) ; save callee-saves general registers
+ stw %r4,-124(%sp)
+ stw %r5,-120(%sp)
+ stw %r6,-116(%sp)
+ stw %r7,-112(%sp)
+ stw %r8,-108(%sp)
+ stw %r9,-104(%sp)
+ stw %r10,-100(%sp)
+ stw %r11,-96(%sp)
+ stw %r12,-92(%sp)
+ stw %r13,-88(%sp)
+ stw %r14,-84(%sp)
+ stw %r15,-80(%sp)
+ stw %r16,-76(%sp)
+ stw %r17,-72(%sp)
+ stw %r18,-68(%sp)
+
+qt_abort
+ copy %arg0,%r22 ; helper to be called by $$dyncall
+ copy %sp,%arg0 ; pass current sp as arg0 to helper
+ copy %arg3,%sp ; set new sp
+
+ .CALL
+ bl $$dyncall,%mrp ; call helper
+ copy %mrp,%rp
+
+ ldw -68(%sp),%r18 ; restore general registers
+ ldw -72(%sp),%r17
+ ldw -76(%sp),%r16
+ ldw -80(%sp),%r15
+ ldw -84(%sp),%r14
+ ldw -88(%sp),%r13
+ ldw -92(%sp),%r12
+ ldw -96(%sp),%r11
+ ldw -100(%sp),%r10
+ ldw -104(%sp),%r9
+ ldw -108(%sp),%r8
+ ldw -112(%sp),%r7
+ ldw -116(%sp),%r6
+ ldw -120(%sp),%r5
+ ldw -124(%sp),%r4
+
+ ldw -148(%sp),%rp ; restore return-pointer
+
+ bv %r0(%rp) ; return to caller
+ ldwm -128(%sp),%r3
+
+ .EXIT
+ .PROCEND
+
+
+qt_block
+ .PROC
+ .CALLINFO CALLER, FRAME=0, SAVE_RP, ENTRY_FR=21
+ .ENTRY
+
+ stw %rp,-20(%sp) ; save rp to old frame-marker
+
+ fstds,ma %fr12,8(%sp) ; save callee-saves float registers
+ fstds,ma %fr13,8(%sp)
+ fstds,ma %fr14,8(%sp)
+ fstds,ma %fr15,8(%sp)
+ fstds,ma %fr16,8(%sp)
+ fstds,ma %fr17,8(%sp)
+ fstds,ma %fr18,8(%sp)
+ fstds,ma %fr19,8(%sp)
+ fstds,ma %fr20,8(%sp)
+ fstds,ma %fr21,8(%sp)
+
+ .CALL
+ bl qt_blocki,%rp
+ ldo 48(%sp),%sp
+
+ ldo -48(%sp),%sp
+
+ fldds,mb -8(%sp),%fr21 ; restore callee-saves float registers
+ fldds,mb -8(%sp),%fr20
+ fldds,mb -8(%sp),%fr19
+ fldds,mb -8(%sp),%fr18
+ fldds,mb -8(%sp),%fr17
+ fldds,mb -8(%sp),%fr16
+ fldds,mb -8(%sp),%fr15
+ fldds,mb -8(%sp),%fr14
+ fldds,mb -8(%sp),%fr13
+
+ ldw -28(%sp),%rp ; restore return-pointer
+
+ bv %r0(%rp) ; return to caller.
+ fldds,mb -8(%sp),%fr12
+
+ .EXIT
+ .PROCEND
+
+
+qt_start
+ .PROC
+ .CALLINFO CALLER, FRAME=0
+ .ENTRY
+
+ copy %r18,%arg0 ; set user arg `pu'.
+ copy %r17,%arg1 ; ... user function pt.
+ copy %r16,%arg2 ; ... user function userf.
+ ; %r22 is a caller-saves register
+ copy %r15,%r22 ; function to be called by $$dyncall
+
+ .CALL ; in=%r22
+ bl $$dyncall,%mrp ; call `only'.
+ copy %mrp,%rp
+
+ bl,n qt_error,%r0 ; `only' erroniously returned.
+
+ .EXIT
+ .PROCEND
+
+
+; Varargs
+;
+; First, call `startup' with the `pt' argument.
+;
+; Next, call the user's function with all arguments.
+; We don't know whether arguments are integers, 32-bit floating-points or
+; even 64-bit floating-points, so we reload all the registers, possibly
+; with garbage arguments. The thread creator provided non-garbage for
+; the arguments that the callee actually uses, so the callee never gets
+; garbage.
+;
+; -48 -44 -40 -36 -32
+; | arg3 | arg2 | arg1 | arg0 |
+; -----------------------------
+; integers: arg3 arg2 arg1 arg0
+; 32-bit fps: farg3 farg2 farg1 farg0
+; 64-bit fps: <---farg3--> <---farg1-->
+;
+; Finally, call `cleanup' with the `pt' argument and with the return value
+; from the user's function. It is an error for `cleanup' to return.
+
+qt_vstart
+ .PROC
+ .CALLINFO CALLER, FRAME=0
+ .ENTRY
+
+ ; Because the startup function may damage the fixed arguments
+ ; on the stack (PA-RISC Procedure Calling Conventions Reference
+ ; Manual, 2.4 Fixed Arguments Area), we allocate a seperate
+ ; stack frame for it.
+ ldo 64(%sp),%sp
+
+ ; call: void startup(void *pt)
+
+ copy %r15,%arg0 ; `pt' is arg0 to `startup'.
+ copy %r16,%r22
+ .CALL
+ bl $$dyncall,%mrp ; Call `startup'.
+ copy %mrp,%rp
+
+ ldo -64(%sp),%sp
+
+ ; call: void *qt_vuserf_t(...)
+
+ ldw -36(%sp),%arg0 ; Load args to integer registers.
+ ldw -40(%sp),%arg1
+ ldw -44(%sp),%arg2
+ ldw -48(%sp),%arg3
+ ; Index of fld[w|d]s only ranges from -16 to 15, so we
+ ; take r22 to be our new base register.
+ ldo -32(%sp),%r22
+ fldws -4(%r22),%farg0 ; Load args to floating-point registers.
+ fldds -8(%r22),%farg1
+ fldws -12(%r22),%farg2
+ fldds -16(%r22),%farg3
+ copy %r17,%r22
+ .CALL
+ bl $$dyncall,%mrp ; Call `userf'.
+ copy %mrp,%rp
+
+ ; call: void cleanup(void *pt, void *vuserf_return)
+
+ copy %r15,%arg0 ; `pt' is arg0 to `cleanup'.
+ copy %ret0,%arg1 ; Return-value is arg1 to `cleanup'.
+ copy %r18,%r22
+ .CALL
+ bl $$dyncall,%mrp ; Call `cleanup'.
+ copy %mrp,%rp
+
+ bl,n qt_error,%r0
+
+ .EXIT
+ .PROCEND
diff --git a/ext/systemc/src/sysc/qt/md/hppa_b.s b/ext/systemc/src/sysc/qt/md/hppa_b.s
new file mode 100644
index 000000000..1b1e8264e
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/hppa_b.s
@@ -0,0 +1,203 @@
+; QuickThreads -- Threads-building toolkit.
+; Copyright (c) 1993 by David Keppel
+
+; Permission to use, copy, modify and distribute this software and
+; its documentation for any purpose and without fee is hereby
+; granted, provided that the above copyright notice and this notice
+; appear in all copies. This software is provided as a
+; proof-of-concept and for demonstration purposes; there is no
+; representation about the suitability of this software for any
+; purpose.
+
+; This file (pa-risc_b.s) is part of the port of QuickThreads for
+; PA-RISC 1.1 architecture. It contains assembly-level support for
+; raw processor performance measurement. It was written in 1994 by
+; Uwe Reder (`uereder@cip.informatik.uni-erlangen.de')
+; for the Operating Systems Department (IMMD4) at the
+; University of Erlangen/Nuernberg Germany.
+
+
+; Note that the number of instructions in the measurement-loops, differ
+; from implementation to implementation. I took eight instructions in a loop
+; for every test (execute eight instructions and loop to the start).
+
+ .CODE
+
+ .IMPORT $global$,DATA
+ .IMPORT $$dyncall,MILLICODE
+ .EXPORT b_call_reg
+ .EXPORT b_call_imm
+ .EXPORT b_add
+ .EXPORT b_load
+
+; Just do nothing, only return to caller. This procedure is called by
+; `b_call_reg' and `b_call_imm'.
+
+b_null
+ .PROC
+ .CALLINFO NO_CALLS, FRAME=0
+ .ENTRY
+
+ bv,n %r0(%rp) ; just return
+
+ .EXIT
+ .PROCEND
+
+; Call the procedure `b_null' with function pointer in a register.
+
+b_call_reg
+ .PROC
+ .CALLINFO CALLER, FRAME=0
+ .ENTRY
+
+ stwm %r3,64(%sp) ; store r3 (may be used by caller)
+ stw %rp,-20(%sp) ; save return-pointer to frame-marker
+
+ addil LR'to_call-$global$,%r27
+ ldw RR'to_call-$global$(%r1),%r3
+
+_loop0
+ copy %r3,%r22 ; copy the procedure label to r22, ...
+ .CALL ; ...this is the input to $$dyncall
+ bl $$dyncall,%mrp ; call $$dyncall (millicode function)
+ copy %mrp,%rp ; remember the return-pointer
+
+ copy %r3,%r22
+ .CALL
+ bl $$dyncall,%mrp
+ copy %mrp,%rp
+
+ copy %r3,%r22
+ .CALL
+ bl $$dyncall,%mrp
+ copy %mrp,%rp
+
+ copy %r3,%r22
+ .CALL
+ bl $$dyncall,%mrp
+ copy %mrp,%rp
+
+ copy %r3,%r22
+ .CALL
+ bl $$dyncall,%mrp
+ copy %mrp,%rp
+
+ copy %r3,%r22
+ .CALL
+ bl $$dyncall,%mrp
+ copy %mrp,%rp
+
+ copy %r3,%r22
+ .CALL
+ bl $$dyncall,%mrp
+ copy %mrp,%rp
+
+ copy %r3,%r22
+ .CALL
+ bl $$dyncall,%mrp
+ copy %mrp,%rp
+
+ addibf,<= -8,%arg0,_loop0 ; decrement counter by 8 and loop
+ nop
+
+ ldw -20(%sp),%rp ; restore return-pointer
+ bv %r0(%rp) ; return to caller
+ ldwm -64(%sp),%r3 ; resore r3 and remove stack frame
+
+ .EXIT
+ .PROCEND
+
+; Call the procedure `b_null' immediate.
+
+b_call_imm
+ .PROC
+ .CALLINFO CALLER, FRAME=0, SAVE_RP
+ .ENTRY
+
+ ldo 64(%sp),%sp ; caller needs a stack-frame
+ stw %rp,-20(%sp) ; save return-pointer to frame-marker
+
+_loop1
+ bl b_null,%rp ; call `b_null' immediate (8 times)
+ nop
+ bl b_null,%rp
+ nop
+ bl b_null,%rp
+ nop
+ bl b_null,%rp
+ nop
+ bl b_null,%rp
+ nop
+ bl b_null,%rp
+ nop
+ bl b_null,%rp
+ nop
+ bl b_null,%rp
+ nop
+
+ addibf,<= -8,%arg0,_loop1 ; decrement counter by 8 and loop
+ nop
+
+ ldw -20(%sp),%rp ; restore return-pointer
+ bv %r0(%rp) ; return to caller
+ ldo -64(%sp),%sp ; remove stack-frame
+
+ .EXIT
+ .PROCEND
+
+; Copy register-to-register.
+; On PA-RISC this is implemented with an `or'.
+; The `or' is hidden by a pseudo-operation called `copy'.
+
+b_add
+ .PROC
+ .CALLINFO NO_CALLS, FRAME=0
+ .ENTRY
+
+_loop2
+ copy %r19,%r20 ; copy register-to-register
+ copy %r20,%r21 ; use caller-saves registers
+ copy %r21,%r22
+ copy %r22,%r21
+ copy %r21,%r20
+ copy %r20,%r19
+ copy %r19,%r20
+ copy %r20,%r21
+
+ addibf,<= -8,%arg0,_loop2 ; decrement counter by 8 and loop
+ nop
+
+ bv,n %r0(%rp)
+
+ .EXIT
+ .PROCEND
+
+; Load memory to a register.
+
+b_load
+ .PROC
+ .CALLINFO NO_CALLS, FRAME=0
+ .ENTRY
+
+_loop3
+ ldw -4(%sp),%r22 ; load data from frame-marker
+ ldw -8(%sp),%r22 ; use a caller-saves register
+ ldw -12(%sp),%r22
+ ldw -16(%sp),%r22
+ ldw -20(%sp),%r22
+ ldw -24(%sp),%r22
+ ldw -28(%sp),%r22
+ ldw -32(%sp),%r22
+
+ addibf,<= -8,%arg0,_loop3 ; decrement counter by 8 and loop
+ nop
+
+ bv,n %r0(%rp)
+
+ .EXIT
+ .PROCEND
+
+
+ .ALIGN 8
+to_call
+ .WORD b_null
diff --git a/ext/systemc/src/sysc/qt/md/i386.README b/ext/systemc/src/sysc/qt/md/i386.README
new file mode 100644
index 000000000..8ffb92198
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/i386.README
@@ -0,0 +1,7 @@
+Note that some machines want labels to have leading underscores,
+while others (e.g. System V) do not. Thus, several labels appear
+duplicated except for the leading underscore, e.g.
+
+ _qt_cswap:
+ qt_cswap:
+
diff --git a/ext/systemc/src/sysc/qt/md/i386.h b/ext/systemc/src/sysc/qt/md/i386.h
new file mode 100644
index 000000000..04513857e
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/i386.h
@@ -0,0 +1,132 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+#ifndef QUICKTHREADS_386_H
+#define QUICKTHREADS_386_H
+
+typedef unsigned long qt_word_t;
+
+/* Thread's initial stack layout on the i386:
+
+ non-varargs:
+
+ +---
+ | arg[2] === `userf' on startup
+ | arg[1] === `pt' on startup
+ | arg[0] === `pu' on startup
+ +---
+ | ret pc === qt_error
+ +---
+ | ret pc === `only' on startup
+ +---
+ | %ebp
+ | %esi
+ | %edi
+ | %ebx <--- qt_t.sp
+ +---
+
+ When a non-varargs thread is started, it ``returns'' directly to
+ the client's `only' function.
+
+ varargs:
+
+ +---
+ | arg[n-1]
+ | ..
+ | arg[0]
+ +---
+ | ret pc === `qt_vstart'
+ +---
+ | %ebp === `startup'
+ | %esi === `cleanup'
+ | %edi === `pt'
+ | %ebx === `vuserf' <--- qt_t.sp
+ +---
+
+ When a varargs thread is started, it ``returns'' to the `qt_vstart'
+ startup code. The startup code calls the appropriate functions. */
+
+
+/* What to do to start a varargs thread running. */
+extern void qt_vstart (void);
+
+
+/* Hold 4 saved regs plus two return pcs (qt_error, qt_start) plus
+ three args. */
+#define QUICKTHREADS_STKBASE (13 * 4)
+
+/* Hold 4 saved regs plus one return pc (qt_vstart). */
+#define QUICKTHREADS_VSTKBASE (5 * 4)
+
+
+/* Stack must be 16-byte aligned at function call instr. (SSE data support) */
+#define QUICKTHREADS_STKALIGN (16)
+
+
+/* Where to place various arguments. */
+#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_PC)
+#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_ARG2)
+#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_ARG1)
+#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_ARG0)
+
+#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_EBP)
+#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_EBX)
+#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_ESI)
+#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_EDI)
+
+
+#define QUICKTHREADS_EBX 0
+#define QUICKTHREADS_EDI 1
+#define QUICKTHREADS_ESI 2
+#define QUICKTHREADS_EBP 3
+#define QUICKTHREADS_POP0 4
+#define QUICKTHREADS_POP1 5
+#define QUICKTHREADS_POP2 6
+#define QUICKTHREADS_PC 7
+/* The following are defined only for non-varargs. */
+#define QUICKTHREADS_POPE 8
+#define QUICKTHREADS_ARG0 9
+#define QUICKTHREADS_ARG1 10
+#define QUICKTHREADS_ARG2 11
+#define QUICKTHREADS_RPC 12
+
+
+/* Stack grows down. The top of the stack is the first thing to
+ pop off (preincrement, postdecrement). */
+#define QUICKTHREADS_GROW_DOWN
+
+extern void qt_error (void);
+
+/* For correct 16-byte stack alignment (auto-relocatable functions) */
+extern void qt_tramp (void);
+extern void qt_align (void);
+
+/* Push on the error return address and the alignment/trampoline functions. */
+#define QUICKTHREADS_ARGS_MD(sto) \
+ (QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP0, qt_align), \
+ QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP1, qt_align), \
+ QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP2, qt_align), \
+ QUICKTHREADS_SPUT (sto, QUICKTHREADS_POPE, qt_tramp), \
+ QUICKTHREADS_SPUT (sto, QUICKTHREADS_RPC, qt_error))
+
+
+/* When varargs are pushed, allocate space for all the args. */
+#define QUICKTHREADS_VARGS_MD0(sto, nbytes) \
+ ((qt_t *)(((char *)(sto)) - QUICKTHREADS_STKROUNDUP(nbytes)))
+
+#define QUICKTHREADS_VARGS_MD1(sto) \
+ (QUICKTHREADS_SPUT (sto, QUICKTHREADS_PC, qt_vstart))
+
+#define QUICKTHREADS_VARGS_DEFAULT
+
+#endif /* QUICKTHREADS_386_H */
diff --git a/ext/systemc/src/sysc/qt/md/i386.s b/ext/systemc/src/sysc/qt/md/i386.s
new file mode 100644
index 000000000..b5806cd27
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/i386.s
@@ -0,0 +1,119 @@
+/* i386.s -- assembly support. */
+
+/*
+// QuickThreads -- Threads-building toolkit.
+// Copyright (c) 1993 by David Keppel
+//
+// Permission to use, copy, modify and distribute this software and
+// its documentation for any purpose and without fee is hereby
+// granted, provided that the above copyright notice and this notice
+// appear in all copies. This software is provided as a
+// proof-of-concept and for demonstration purposes; there is no
+// representation about the suitability of this software for any
+// purpose. */
+
+/* NOTE: double-labeled `_name' and `name' for System V compatability. */
+/* NOTE: Mixed C/C++-style comments used. Sorry! */
+
+/* Callee-save: %esi, %edi, %ebx, %ebp
+// Caller-save: %eax, %ecx
+// Can't tell: %edx (seems to work w/o saving it.)
+//
+// Assignment:
+//
+// See ``i386.h'' for the somewhat unconventional stack layout. */
+
+
+ .text
+ .align 2
+
+ .globl _qt_abort
+ .globl qt_abort
+ .globl _qt_block
+ .globl qt_block
+ .globl _qt_blocki
+ .globl qt_blocki
+ .globl _qt_align
+ .globl qt_align
+
+/* These all have the type signature
+//
+// void *blocking (helper, arg0, arg1, new)
+//
+// On procedure entry, the helper is at 4(sp), args at 8(sp) and
+// 12(sp) and the new thread's sp at 16(sp). It *appears* that the
+// calling convention for the 8X86 requires the caller to save all
+// floating-point registers, this makes our life easy. */
+
+/* Halt the currently-running thread. Save it's callee-save regs on
+// to the stack, 32 bytes. Switch to the new stack (next == 16+32(sp))
+// and call the user function (f == 4+32(sp) with arguments: old sp
+// arg1 (8+32(sp)) and arg2 (12+32(sp)). When the user function is
+// done, restore the new thread's state and return.
+//
+// `qt_abort' is (currently) an alias for `qt_block' because most of
+// the work is shared. We could save the insns up to `qt_common' by
+// replicating, but w/o replicating we need an inital subtract (to
+// offset the stack as if it had been a qt_block) and then a jump
+// to qt_common. For the cost of a jump, we might as well just do
+// all the work.
+//
+// The helper function (4(sp)) can return a void* that is returned
+// by the call to `qt_blockk{,i}'. Since we don't touch %eax in
+// between, we get that ``for free''. */
+
+_qt_abort:
+qt_abort:
+_qt_block:
+qt_block:
+_qt_blocki:
+qt_blocki:
+ pushl %ebp /* Save callee-save, sp-=4. */
+ pushl %esi /* Save callee-save, sp-=4. */
+ pushl %edi /* Save callee-save, sp-=4. */
+ pushl %ebx /* Save callee-save, sp-=4. */
+ movl %esp, %eax /* Remember old stack pointer. */
+
+qt_common:
+ movl 32(%esp), %esp /* Move to new thread. */
+ pushl 28(%eax) /* Push arg 2. */
+ pushl 24(%eax) /* Push arg 1. */
+ pushl %eax /* Push arg 0. */
+ movl 20(%eax), %ebx /* Get function to call. */
+ call *%ebx /* Call f. */
+ addl $12, %esp /* Pop args. */
+
+ popl %ebx /* Restore callee-save, sp+=4. */
+ popl %edi /* Restore callee-save, sp+=4. */
+ popl %esi /* Restore callee-save, sp+=4. */
+ popl %ebp /* Restore callee-save, sp+=4. */
+_qt_align:
+qt_align:
+ ret /* Resume the stopped function. */
+
+ .globl _qt_tramp
+ .globl qt_tramp
+_qt_tramp:
+qt_tramp:
+ movl 12(%esp), %eax /* Load 'qt_error' address */
+ sub $4, %esp /* Align stack pointer to 16-byte boundary */
+ jmp *%eax /* call 'qt_error' */
+ hlt /* 'qt_error' never returns */
+
+/* Start a varargs thread. */
+
+ .globl _qt_vstart
+ .globl qt_vstart
+_qt_vstart:
+qt_vstart:
+ pushl %edi /* Push `pt' arg to `startup'. */
+ call *%ebp /* Call `startup'. */
+ popl %eax /* Clean up the stack. */
+
+ call *%ebx /* Call the user's function. */
+
+ pushl %eax /* Push return from user's. */
+ pushl %edi /* Push `pt' arg to `cleanup'. */
+ call *%esi /* Call `cleanup'. */
+
+ hlt /* `cleanup' never returns. */
diff --git a/ext/systemc/src/sysc/qt/md/i386_b.s b/ext/systemc/src/sysc/qt/md/i386_b.s
new file mode 100644
index 000000000..32129a5d1
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/i386_b.s
@@ -0,0 +1,30 @@
+/*
+// QuickThreads -- Threads-building toolkit.
+// Copyright (c) 1993 by David Keppel
+//
+// Permission to use, copy, modify and distribute this software and
+// its documentation for any purpose and without fee is hereby
+// granted, provided that the above copyright notice and this notice
+// appear in all copies. This software is provided as a
+// proof-of-concept and for demonstration purposes; there is no
+// representation about the suitability of this software for any
+// purpose. */
+
+ .globl _b_call_reg
+ .globl b_call_reg
+ .globl _b_call_imm
+ .globl b_call_imm
+ .globl _b_add
+ .globl b_add
+ .globl _b_load
+ .globl b_load
+
+_b_call_reg:
+b_call_reg:
+_b_call_imm:
+b_call_imm:
+_b_add:
+b_add:
+_b_load:
+b_load:
+ hlt
diff --git a/ext/systemc/src/sysc/qt/md/iX86_64.h b/ext/systemc/src/sysc/qt/md/iX86_64.h
new file mode 100644
index 000000000..97bfe39b4
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/iX86_64.h
@@ -0,0 +1,140 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+#ifndef QUICKTHREADS_X86_64_H
+#define QUICKTHREADS_X86_64_H
+
+typedef unsigned long qt_word_t;
+
+/* Thread's initial stack layout on the iX86_64:
+
+ non-varargs:
+
+ +---
+ | arg[2] === `userf' on startup
+ | arg[1] === `pt' on startup
+ | arg[0] === `pu' on startup
+ +---
+ | ret pc === qt_error
+ +---
+ | ret pc === `only' on startup
+ +---
+ | %ebp
+ | %esi
+ | %edi
+ | %ebx <--- qt_t.sp
+ +---
+
+ When a non-varargs thread is started, it ``returns'' directly to
+ the client's `only' function.
+
+ varargs:
+
+ +---
+ | arg[n-1]
+ | ..
+ | arg[0]
+ +---
+ | ret pc === `qt_vstart'
+ +---
+ | %ebp === `startup'
+ | %esi === `cleanup'
+ | %edi === `pt'
+ | %ebx === `vuserf' <--- qt_t.sp
+ +---
+
+ When a varargs thread is started, it ``returns'' to the `qt_vstart'
+ startup code. The startup code calls the appropriate functions. */
+
+
+/* What to do to start a varargs thread running. */
+extern void qt_vstart (void);
+
+
+/* Hold four return pcs (qt_error, qt_start and twice qt_align)
+ plus ten args and two qt_word_t's for correct alignment. */
+#define QUICKTHREADS_STKBASE (16 * sizeof(long))
+
+/* Hold 4 saved regs plus one return pc (qt_vstart). */
+#define QUICKTHREADS_VSTKBASE (5 * sizeof(long))
+
+
+/* Stack must be 16-byte aligned at function call instr. (SSE data support) */
+#define QUICKTHREADS_STKALIGN (16)
+
+
+/* Where to place various arguments. */
+#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_PC)
+#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_ARG2)
+#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_ARG1)
+#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_ARG0)
+
+#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_EBP)
+#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_EBX)
+#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_ESI)
+#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_EDI)
+
+
+/* Stack layout offsets relative to stack at initial stack setup. */
+
+/* Stack alignment 15 */
+#define QUICKTHREADS_RPC 14
+#define QUICKTHREADS_POP0 13
+#define QUICKTHREADS_PC 12
+#define QUICKTHREADS_POP1 11
+#define QUICKTHREADS_RBP 10
+/* Stack alignment 9 */
+#define QUICKTHREADS_R12 8
+#define QUICKTHREADS_R13 7
+#define QUICKTHREADS_R14 6
+#define QUICKTHREADS_R15 5
+#define QUICKTHREADS_RBX 4
+#define QUICKTHREADS_RCX 3
+#define QUICKTHREADS_RDX 2
+#define QUICKTHREADS_RDI 1
+#define QUICKTHREADS_RSI 0
+
+
+/* Arguments to save stack function. */
+
+#define QUICKTHREADS_ARG0 QUICKTHREADS_RDI
+#define QUICKTHREADS_ARG1 QUICKTHREADS_RSI
+#define QUICKTHREADS_ARG2 QUICKTHREADS_RDX
+
+
+/* Stack grows down. The top of the stack is the first thing to
+ pop off (preincrement, postdecrement). */
+#define QUICKTHREADS_GROW_DOWN
+
+extern void qt_error (void);
+extern void qt_align (void); /* For correct stack alignment */
+
+/* Push on the error return address, force Frame Pointer to 0 and
+ push stack alignment trampoline function. */
+#define QUICKTHREADS_ARGS_MD(sto) \
+ (QUICKTHREADS_SPUT (sto, QUICKTHREADS_RBP, 0), \
+ QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP0, qt_align), \
+ QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP1, qt_align), \
+ QUICKTHREADS_SPUT (sto, QUICKTHREADS_RPC, qt_error))
+
+
+/* When varargs are pushed, allocate space for all the args. */
+#define QUICKTHREADS_VARGS_MD0(sto, nbytes) \
+ ((qt_t *)(((char *)(sto)) - QUICKTHREADS_STKROUNDUP(nbytes)))
+
+#define QUICKTHREADS_VARGS_MD1(sto) \
+ (QUICKTHREADS_SPUT (sto, QUICKTHREADS_PC, qt_vstart))
+
+#define QUICKTHREADS_VARGS_DEFAULT
+
+#endif /* QUICKTHREADS_X86_64_H */
diff --git a/ext/systemc/src/sysc/qt/md/iX86_64.s b/ext/systemc/src/sysc/qt/md/iX86_64.s
new file mode 100644
index 000000000..a8bcfcd96
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/iX86_64.s
@@ -0,0 +1,74 @@
+/* iX386_64.s -- assembly support. */
+
+/*
+// QuickThreads -- Threads-building toolkit.
+// Copyright (c) 1993 by David Keppel
+//
+// Permission to use, copy, modify and distribute this software and
+// its documentation for any purpose and without fee is hereby
+// granted, provided that the above copyright notice and this notice
+// appear in all copies. This software is provided as a
+// proof-of-concept and for demonstration purposes; there is no
+// representation about the suitability of this software for any
+// purpose. */
+
+/* 64-bit Intel Architecture Support
+// written by Andy Goodrich, Forte Design Systms, Inc. */
+
+/* NOTE: double-labeled `_name' and `name' for System V compatability. */
+/* NOTE: Mixed C/C++-style comments used. Sorry! */
+
+ .text
+ .align 2
+
+ .globl _qt_abort
+ .globl qt_abort
+ .globl _qt_block
+ .globl qt_block
+ .globl _qt_blocki
+ .globl qt_blocki
+ .globl _qt_align
+ .globl qt_align
+
+_qt_abort:
+qt_abort:
+_qt_block:
+qt_block:
+_qt_blocki:
+qt_blocki:
+ /* 11 (return address.) */
+ pushq %rbp /* 10 (push stack frame top.) */
+ movq %rsp, %rbp /* set new stack frame top. */
+ /* save registers. */
+ subq $8, %rsp /* 9 (Stack alignment) */
+ pushq %r12 /* 8 ... */
+ pushq %r13 /* 7 ... */
+ pushq %r14 /* 6 ... */
+ pushq %r15 /* 5 ... */
+ pushq %rbx /* 4 ... */
+ pushq %rcx /* 3 ... (new stack address) */
+ pushq %rdx /* 2 ... (arg) */
+ pushq %rdi /* 1 ... (address of save function.) */
+ pushq %rsi /* 0 ... (cor) */
+
+ movq %rdi, %rax /* get address of save function. */
+ movq %rsp, %rdi /* set current stack as save argument. */
+ movq %rcx, %rsp /* swap stacks. */
+ movq %rcx, %rbp /* adjust stack frame pointer. */
+ addq $10*8, %rbp /* ... */
+ call *%rax /* call function to save stack pointer. */
+
+ /* restore registers. */
+ popq %rsi /* ... */
+ popq %rdi /* ... */
+ popq %rdx /* ... */
+ popq %rcx /* ... */
+ popq %rbx /* ... */
+ popq %r15 /* restore registers from new stack. */
+ popq %r14 /* ... */
+ popq %r13 /* ... */
+ popq %r12 /* ... */
+ leave /* unwind stack. */
+_qt_align:
+qt_align:
+ ret /* return. */
diff --git a/ext/systemc/src/sysc/qt/md/ksr1.Makefile b/ext/systemc/src/sysc/qt/md/ksr1.Makefile
new file mode 100644
index 000000000..aa195839a
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/ksr1.Makefile
@@ -0,0 +1,6 @@
+
+#
+# KSR1 configuration.
+#
+CC = cc -ansi
+
diff --git a/ext/systemc/src/sysc/qt/md/ksr1.h b/ext/systemc/src/sysc/qt/md/ksr1.h
new file mode 100644
index 000000000..b3877505d
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/ksr1.h
@@ -0,0 +1,164 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+#ifndef QUICKTHREADS_KSR1_H
+#define QUICKTHREADS_KSR1_H
+
+/*
+ Stack layout:
+
+ Registers are saved in strictly low to high order, FPU regs first
+ (only if qt_block is called), CEU regs second, IPU regs next, with no
+ padding between the groups.
+
+ Callee-save: f16..f63; c15..c30; i12..i30.
+ Args passed in i2..i5.
+
+ Note: c31 is a private data pointer. It is not changed on thread
+ swaps with the assumption that it represents per-processor rather
+ than per-thread state.
+
+ Note: i31 is an instruction count register that is updated by the
+ context switch routines. Like c31, it is not changed on context
+ switches.
+
+ This is what we want on startup:
+
+
+ +------ <-- BOS: Bottom of stack (grows down)
+ | 80 (128 - 48) bytes of padding to a 128-byte boundary
+ +---
+ | only
+ | userf
+ | t
+ | u
+ | qt_start$TXT
+ | (empty) <-- qt.sp
+ +------ <-- (BOS - 128)
+
+ This is why we want this on startup:
+
+ A thread begins running when the restore procedure switches thread stacks
+ and pops a return address off of the top of the new stack (see below
+ for the reason why we explicitly store qt_start$TXT). The
+ block procedure pushes two jump addresses on a thread's stack before
+ it switches stacks. The first is the return address for the block
+ procedure, and the second is a restore address. The return address
+ is used to jump back to the thread that has been switched to; the
+ restore address is a jump within the block code to restore the registers.
+ Normally, this is just a jump to the next address. However, on thread
+ startup, this is a jump to qt_start$TXT. (The block procedure stores
+ the restore address at an offset of 8 bytes from the top of the stack,
+ which is also the offset at which qt_start$TXT is stored on the stacks
+ of new threads. Hence, when the block procedure switches to a new
+ thread stack, it will initially jump to qt_start$TXT; thereafter,
+ it jumps to the restore code.)
+
+ qt_start$TXT, after it has read the initial data on the new thread's
+ stack and placed it in registers, pops the initial stack frame
+ and gives the thread the entire stack to use for execution.
+
+ The KSR runtime system has an unusual treatment of pointers to
+ functions. From C, taking the `name' of a function yields a
+ pointer to a _constant block_ and *not* the address of the
+ function. The zero'th entry in the constant block is a pointer to
+ the function.
+
+ We have to be careful: the restore procedure expects a return
+ address on the top of the stack (pointed to by qt.sp). This is not
+ a problem when restoring a thread that has run before, since the
+ block routine would have stored the return address on top of the
+ stack. However, when ``faking up'' a thread start (bootstrapping a
+ thread stack frame), the top of the stack needs to contain a
+ pointer to the code that will start the thread running.
+
+ The pointer to the startup code is *not* `qt_start'. It is the
+ word *pointed to* by `qt_start'. Thus, we dereference `qt_start',
+ see QUICKTHREADS_ARGS_MD below.
+
+ On varargs startup (still unimplemented):
+
+ | padding to 128 byte boundary
+ | varargs <-- padded to a 128-byte-boundary
+ +---
+ | caller's frame, 16 bytes
+ | 80 bytes of padding (frame padded to a 128-byte boundary)
+ +---
+ | cleanup
+ | vuserf
+ | startup
+ | t
+ +---
+ | qt_start <-- qt.sp
+ +---
+
+ Of a suspended thread:
+
+ +---
+ | caller's frame, 16 bytes
+ | fpu registers 47 regs * 8 bytes/reg 376 bytes
+ | ceu registers 16 regs * 8 bytes/reg 128 bytes
+ | ipu registers 19 regs * 8 bytes/reg 152 bytes
+ | :
+ | 80 bytes of padding
+ | :
+ | qt_restore <-- qt.sp
+ +---
+
+ */
+
+
+#define QUICKTHREADS_STKALIGN 128
+#define QUICKTHREADS_GROW_DOWN
+typedef unsigned long qt_word_t;
+
+#define QUICKTHREADS_STKBASE QUICKTHREADS_STKALIGN
+#define QUICKTHREADS_VSTKBASE QUICKTHREADS_STKBASE
+
+extern void qt_start(void);
+/*
+ * See the discussion above for what indexing into a procedure ptr
+ * does for us (it's lovely, though, isn't it?).
+ *
+ * This assumes that the address of a procedure's code is the
+ * first word in a procedure's constant block. That's how the manual
+ * says it will be arranged.
+ */
+#define QUICKTHREADS_ARGS_MD(sp) (QUICKTHREADS_SPUT (sp, 1, ((qt_word_t *)qt_start)[0]))
+
+/*
+ * The *index* (positive offset) of where to put each value.
+ * See the picture of the stack above that explains the offsets.
+ */
+#define QUICKTHREADS_ONLY_INDEX (5)
+#define QUICKTHREADS_USER_INDEX (4)
+#define QUICKTHREADS_ARGT_INDEX (3)
+#define QUICKTHREADS_ARGU_INDEX (2)
+
+#define QUICKTHREADS_VARGS_DEFAULT
+#define QUICKTHREADS_VARGS(sp, nb, vargs, pt, startup, vuserf, cleanup) \
+ (qt_vargs (sp, nbytes, &vargs, pt, startup, vuserf, cleanup))
+
+
+#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \
+ ((qt_t *)(((char *)(sp)) - 4*8 - QUICKTHREADS_STKROUNDUP(vabytes)))
+
+extern void qt_vstart(void);
+#define QUICKTHREADS_VARGS_MD1(sp) (QUICKTHREADS_SPUT (sp, 0, ((qt_word_t *)qt_vstart)[0]))
+
+#define QUICKTHREADS_VCLEANUP_INDEX (4)
+#define QUICKTHREADS_VUSERF_INDEX (3)
+#define QUICKTHREADS_VSTARTUP_INDEX (2)
+#define QUICKTHREADS_VARGT_INDEX (1)
+
+#endif /* def QUICKTHREADS_KSR1_H */
diff --git a/ext/systemc/src/sysc/qt/md/ksr1.s b/ext/systemc/src/sysc/qt/md/ksr1.s
new file mode 100644
index 000000000..d4d51a0a6
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/ksr1.s
@@ -0,0 +1,424 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+ .file "ksr1.s"
+ .def .debug; .endef
+
+ .align 128
+ .globl qt_blocki
+ .globl qt_blocki$TXT
+ .globl qt_block
+ .globl qt_block$TXT
+ .globl qt_start$TXT
+ .globl qt_start
+ .globl qt_abort$TXT
+ .globl qt_abort
+ .globl qt_vstart
+ .globl qt_vstart$TXT
+
+#
+# KSR convention: on procedure calls, load both the procedure address
+# and a pointer to a constant block. The address of function `f' is
+# `f$TXT', and the constant block address is `f'. The constant block
+# has several reserved values:
+#
+# 8 bytes fpu register save mask
+# 4 bytes ipu register save mask
+# 4 bytes ceu register save mask
+# f: f$TXT
+# ... whatever you want ... (not quite...read on)
+#
+# Note, by the way, that a pointer to a function is passed as a
+# pointer to the constant area, and the constant area has the text
+# address.
+#
+
+#
+# Procedures that do not return structures prefix their code with
+#
+# proc$TXT:
+# finop; cxnop
+# finop; cxnop
+# <proc code>
+#
+# Calls to those procedures branch to a 16 byte offset (4 instrs) in
+# to the procedure to skip those instructions.
+#
+# Procedures that return structures use a different code prefix:
+#
+# proc$TXT:
+# finop; beq.qt %rc, %rc, 24 # return value entry
+# finop; cxnop
+# finop; movi8 0, %rc # no return value entry
+# <proc code>
+#
+# Calls that want the returned structure branch directly to the
+# procedure address. Callers that don't want (or aren't expecting) a
+# return value branche 16 bytes in to the procedure, which will zero
+# %rc, telling the called procedure not to return a structure.
+#
+
+#
+# On entry:
+# %i2 -- control block of helper function to run
+# (dereference to get helper)
+# %i3 -- a1
+# %i4 -- a2
+# %i5 -- sp of new to run
+#
+
+ .data
+ .half 0x0, 0x0, 0x7ffff000, 0x7fff8000
+qt_blocki:
+qt_abort:
+ .word qt_blocki$TXT
+ .word qt_restore$TXT
+
+ .text
+qt_abort$TXT:
+qt_blocki$TXT:
+ finop ; cxnop # entry prefix
+ finop ; cxnop # entry prefix
+ add8.ntr 75,%i31,%i31 ; movi8 512,%c5 # ICR; stk adjust
+ finop ; ssub8.ntr 0,%sp,%c5,%sp
+ finop ; st8 %fp,504(%sp) # Save caller's fp
+ finop ; st8 %cp,496(%sp) # Save caller's cp
+ finop ; ld8 8(%c10),%c5 # ld qt_restore$TXT
+ finop ; st8 %c14,0(%sp) # Save special ret addr
+ finop ; mov8_8 %c10, %cp # Our cp
+ finop ; sadd8.ntr 0,%sp,%c5,%fp # Our frame ptr
+ finop ; st8 %c5,8(%sp) # st qt_restore$TXT
+#
+# CEU registers %c15-%c24, %c26-%c30 (%c14 we restore later)
+#
+ finop ; st8 %c15,456(%sp)
+ finop ; st8 %c16,448(%sp)
+ finop ; st8 %c17,440(%sp)
+ finop ; st8 %c18,432(%sp)
+ finop ; st8 %c19,424(%sp)
+ finop ; st8 %c20,416(%sp)
+ finop ; st8 %c21,408(%sp)
+ finop ; st8 %c22,400(%sp)
+ finop ; st8 %c23,392(%sp)
+ finop ; st8 %c24,384(%sp)
+#
+# %c25 is the Enclosing Frame Pointer (EFP) -- since C doesn't
+# use nested procedures, we ignore it (leaving a gap, though)
+#
+ finop ; st8 %c26,368(%sp)
+ finop ; st8 %c27,360(%sp)
+ finop ; st8 %c28,352(%sp)
+ finop ; st8 %c29,344(%sp)
+ finop ; st8 %c30,336(%sp)
+#
+# IPU registers %i12-%i30
+#
+ finop ; st8 %i12,328(%sp)
+ finop ; st8 %i13,320(%sp)
+ finop ; st8 %i14,312(%sp)
+ finop ; st8 %i15,304(%sp)
+# (gap to get alignment for st64)
+# -- Doesn't work on version 1.1.3 of the OS
+# finop ; st64 %i16,256(%sp)
+
+ finop ; st8 %i16,256(%sp)
+ finop ; st8 %i17,248(%sp)
+ finop ; st8 %i18,240(%sp)
+ finop ; st8 %i19,232(%sp)
+ finop ; st8 %i20,224(%sp)
+ finop ; st8 %i21,216(%sp)
+ finop ; st8 %i22,208(%sp)
+ finop ; st8 %i23,200(%sp)
+ finop ; st8 %i24,192(%sp)
+ finop ; st8 %i25,184(%sp)
+ finop ; st8 %i26,176(%sp)
+ finop ; st8 %i27,168(%sp)
+ finop ; st8 %i28,160(%sp)
+ finop ; st8 %i29,152(%sp)
+ finop ; st8 %i30,144(%sp)
+#
+# FPU already saved, or saving not necessary
+#
+
+#
+# Switch to the stack passed in as fourth argument to the block
+# routine (%i5) and call the helper routine passed in as the first
+# argument (%i2). Note that the address of the helper's constant
+# block is passed in, so we must derefence it to get the helper's text
+# address.
+#
+ finop ; movb8_8 %i2,%c10 # helper's ConstBlock
+ finop ; cxnop # Delay slot, fill w/
+ finop ; cxnop # .. 2 st8 from above
+ finop ; ld8 0(%c10),%c4 # load addr of helper
+ finop ; movb8_8 %sp, %i2 # 1st arg to helper
+ # is this stack; other
+ # args remain in regs
+ finop ; movb8_8 %i5,%sp # switch stacks
+ finop ; jsr %c14,16(%c4) # call helper
+ movi8 3, %i0 ; movi8 0,%c8 # nargs brain dmg
+ finop ; cxnop
+ finop ; cxnop
+#
+# Here is where behavior differs for threads being restored and threads
+# being started. Blocked threads have a pointer to qt_restore$TXT on
+# the top of their stacks; manufactured stacks have a pointer to qt_start$TXT
+# on the top of their stacks. With this setup, starting threads
+# skip the (unecessary) restore operations.
+#
+# We jump to an offset of 16 to either (1) skip past the two noop pairs
+# at the start of qt_start$TXT, or (2) skip past the two noop pairs
+# after qt_restore$TXT.
+#
+ finop ; ld8 8(%sp),%c4
+ finop ; cxnop
+ finop ; cxnop
+ finop ; jmp 16(%c4)
+qt_restore$TXT:
+ finop ; cxnop
+ finop ; cxnop
+#
+# Point of Restore:
+#
+# The helper funtion will return here. Any result it has placed in
+# a return register (most likely %i0) will not get overwritten below
+# and will consequently be the return value of the blocking routine.
+#
+
+#
+# CEU registers %c15-%c24, %c26-%c30 (%c14 we restore later)
+#
+ finop ; ld8 456(%sp),%c15
+ finop ; ld8 448(%sp),%c16
+ finop ; ld8 440(%sp),%c17
+ finop ; ld8 432(%sp),%c18
+ finop ; ld8 424(%sp),%c19
+ finop ; ld8 416(%sp),%c20
+ finop ; ld8 408(%sp),%c21
+ finop ; ld8 400(%sp),%c22
+ finop ; ld8 392(%sp),%c23
+ finop ; ld8 384(%sp),%c24
+#
+# %c25 is the Enclosing Frame Pointer (EFP) -- since C doesn't
+# use nested procedures, we ignore it (leaving a gap, though)
+#
+ finop ; ld8 368(%sp),%c26
+ finop ; ld8 360(%sp),%c27
+ finop ; ld8 352(%sp),%c28
+ finop ; ld8 344(%sp),%c29
+ finop ; ld8 336(%sp),%c30
+#
+# IPU registers %i12-%i30
+#
+ finop ; ld8 328(%sp),%i12
+ finop ; ld8 320(%sp),%i13
+ finop ; ld8 312(%sp),%i14
+ finop ; ld8 304(%sp),%i15
+# (gap to get alignment for ld64)
+# -- Doesn't work on version 1.1.3 of the OS
+# finop ; ld64 256(%sp),%i16
+
+ finop ; ld8 256(%sp),%i16
+ finop ; ld8 248(%sp),%i17
+ finop ; ld8 240(%sp),%i18
+ finop ; ld8 232(%sp),%i19
+ finop ; ld8 224(%sp),%i20
+ finop ; ld8 216(%sp),%i21
+ finop ; ld8 208(%sp),%i22
+ finop ; ld8 200(%sp),%i23
+ finop ; ld8 192(%sp),%i24
+ finop ; ld8 184(%sp),%i25
+ finop ; ld8 176(%sp),%i26
+ finop ; ld8 168(%sp),%i27
+ finop ; ld8 160(%sp),%i28
+ finop ; ld8 152(%sp),%i29
+ finop ; ld8 144(%sp),%i30
+
+#
+# FPU registers don't need to be loaded, or will be loaded by an
+# enclosing scope (e.g., if this is called by qt_block).
+#
+
+#
+# Load the special registers. We don't load the stack ptr because
+# the new stack is passed in as an argument, we don't load the EFP
+# because we don't use it, and we load the return address specially
+# off the top of the stack.
+#
+ finop ; ld8 0(%sp),%c14 # return addr
+ finop ; ld8 496(%sp),%cp
+ finop ; ld8 504(%sp),%fp
+
+ finop ; jmp 32(%c14) # jump back to thread
+ finop ; movi8 512,%c5 # stack adjust
+ finop ; sadd8.ntr 0,%sp,%c5,%sp
+
+ .data
+ .half 0x0, 0x0, 0x7ffff000, 0x7fff8000
+qt_block:
+ .word qt_block$TXT
+ .word qt_error
+ .word qt_error$TXT
+ .word qt_blocki
+#
+# Handle saving and restoring the FPU regs, relying on qt_blocki
+# to save and restore the remaining registers.
+#
+ .text
+qt_block$TXT:
+ finop ; cxnop # entry prefix
+ finop ; cxnop # entry prefix
+
+ add8.ntr 29,%i31,%i31 ; movi8 512,%c5 # ICR; stk adjust
+ finop ; ssub8.ntr 0,%sp,%c5,%sp
+ finop ; st8 %fp,504(%sp) # Save caller's fp
+ finop ; st8 %cp,496(%sp) # Save caller's cp
+ finop ; st8 %c14,488(%sp) # store ret addr
+ finop ; sadd8.ntr 0,%sp,%c5,%fp # Our frame ptr
+ finop ; mov8_8 %c10, %cp # Our cp
+
+#
+# Store 8 registers at once...destination must be a multiple of 64
+#
+ finop ; st64 %f16,384(%sp)
+ finop ; st64 %f24,320(%sp)
+ finop ; st64 %f32,256(%sp)
+ finop ; st64 %f40,192(%sp)
+ finop ; st64 %f48,128(%sp)
+ finop ; st64 %f56,64(%sp)
+
+#
+# Call the integer blocking routine, passing the arguments passed to us
+#
+ finop ; ld8 24(%cp), %c10
+ finop ; cxnop
+ finop ; jsr %c14, qt_blocki$TXT
+ finop ; cxnop
+ finop ; cxnop
+ movi8 4,%i0 ; movi8 0,%c8 # nargs brain dmg
+
+#
+# Load 8 registers at once...source must be a multiple of 64
+#
+ finop ; ld64 64(%sp),%f56
+ finop ; ld64 128(%sp),%f48
+ finop ; ld64 192(%sp),%f40
+ finop ; ld64 256(%sp),%f32
+ finop ; ld64 320(%sp),%f24
+ finop ; ld64 384(%sp),%f16
+
+ finop ; ld8 488(%sp),%c14
+ finop ; ld8 496(%sp),%cp
+ finop ; ld8 504(%sp),%fp
+ finop ; jmp 32(%c14) # jump back to thread
+ finop ; movi8 512,%c5 # stack adjust
+ finop ; sadd8.ntr 0,%sp,%c5,%sp
+
+
+ .data
+ .half 0x0, 0x0, 0x7ffff000, 0x7fff8000
+qt_start:
+ .word qt_start$TXT
+#
+# A new thread is set up to "appear" as if it were executing code at
+# the beginning of qt_start and then it called a blocking routine
+# (qt_blocki). So when a new thread starts to run, it gets unblocked
+# by the code above and "returns" to `qt_start$TXT' in the
+# restore step of the switch. Blocked threads jump to 16(qt_restore$TXT),
+# and starting threads jump to 16(qt_start$TXT).
+#
+ .text
+qt_start$TXT:
+ finop ; cxnop #
+ finop ; cxnop #
+ finop ; ld8 40(%sp),%c10 # `only' constant block
+ finop ; ld8 32(%sp),%i4 # `userf' arg.
+ finop ; ld8 24(%sp),%i3 # `t' arg.
+ finop ; ld8 0(%c10),%c4 # `only' text location
+ finop ; ld8 16(%sp),%i2 # `u' arg.
+ finop ; cxnop
+ finop ; jsr %c14,16(%c4) # call `only'
+#
+# Pop the frame used to store the thread's initial data
+#
+ finop ; sadd8.ntr 0,%sp,128,%sp
+ finop ; cxnop
+ movi8 2,%i0 ; movi8 0,%c8 # nargs brain dmg
+#
+# If we ever return, it's an error.
+#
+ finop ; jmp qt_error$TXT
+ finop ; cxnop
+ finop ; cxnop
+ movi8 0,%i0 ; movi8 0,%c8 # nargs brain dmg
+
+
+#
+# This stuff is broken
+#
+ .data
+ .half 0x0, 0x0, 0x7ffff000, 0x7fff8000
+qt_vstart:
+ .word qt_vstart$TXT
+
+ .text
+qt_vstart$TXT:
+ finop ; cxnop # entry prefix
+ finop ; cxnop # entry prefix
+ finop ; cxnop
+ finop ; cxnop
+ add8.ntr 11,%i31,%i31 ; movi8 512,%c5
+ finop ; ssub8.ntr 0,%sp,%c5,%sp # fix stack
+ finop ; ld8 8(%sp),%i2 # load `t' as arg to
+ finop ; cxnop # `startup'
+ finop ; cxnop
+ finop ; ld8 16(%sp),%c10 # `startup' const block
+ finop ; cxnop
+ finop ; cxnop
+ finop ; ld8 0(%c10),%c4 # `startup' text loc.
+ finop ; cxnop
+ finop ; cxnop
+ finop ; jsr %c14,16(%c4) # call `startup'
+ finop ; cxnop
+ finop ; cxnop
+ movi8 1, %i0 ; movi8 0,%c8 # nargs brain dmg
+#
+# finop ; sadd 0,%sp,128,%sp # alter stack
+#
+ finop ; ld8 8(%sp),%i2 # load `t' as arg to
+ finop ; ld8 8(%sp),%i2 # load `t' as arg to
+ finop ; ld8 8(%sp),%i2 # load `t' as arg to
+ finop ; ld8 8(%sp),%i2 # load `t' as arg to
+
+ finop ; ld8 32(%sp),%c10 # `only' constant block
+ finop ; ld8 8(%sp),%i2 # `u' arg.
+ finop ; ld8 16(%sp),%i3 # `t' arg.
+ finop ; ld8 0(%c10),%c4 # `only' text location
+ finop ; ld8 24(%sp),%i4 # `userf' arg.
+ finop ; cxnop
+ finop ; jsr %c4,16(%c4) # call `only'
+ finop ; cxnop
+ finop ; cxnop
+#
+# If the callee ever calls `nargs', the following instruction (pair)
+# will be executed. However, we don't know when we compile this code
+# how many args are being passed. So we give our best guess: 0.
+#
+ movi8 0,%i0 ; movi8 0,%c8 # nargs brain dmg
+#
+# If we ever return, it's an error.
+#
+ finop ; jmp qt_error$TXT
+ finop ; cxnop
+ finop ; cxnop
+ movi8 0,%i0 ; movi8 0,%c8 # nargs brain dmg
diff --git a/ext/systemc/src/sysc/qt/md/ksr1_b.s b/ext/systemc/src/sysc/qt/md/ksr1_b.s
new file mode 100644
index 000000000..80b0c59eb
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/ksr1_b.s
@@ -0,0 +1,49 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+ .file "ksr1_b.s"
+ .def .debug; .endef
+
+ .globl b_call_reg$TXT
+ .globl b_call_reg
+ .globl b_call_imm$TXT
+ .globl b_call_imm
+ .globl b_add$TXT
+ .globl b_add
+ .globl b_load$TXT
+ .globl b_load
+
+
+b_call_reg:
+b_call_imm:
+b_add:
+b_load:
+ .word b_call_reg$TXT
+ .word qt_error
+ .word qt_error$TXT
+
+
+b_call_reg$TXT:
+b_call_imm$TXT:
+b_add$TXT:
+b_load$TXT:
+ finop ; cxnop
+ finop ; cxnop
+ finop ; ld8 16(%cp),%c4
+ finop ; ld8 8(%cp),%cp
+ finop ; cxnop
+ finop ; cxnop
+ finop ; jsr %c4,0(%c4)
+ finop ; cxnop
+ finop ; cxnop
+
diff --git a/ext/systemc/src/sysc/qt/md/m88k.Makefile b/ext/systemc/src/sysc/qt/md/m88k.Makefile
new file mode 100644
index 000000000..608c70690
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/m88k.Makefile
@@ -0,0 +1,6 @@
+
+#
+# Hosted compilers for 88k for Meerkat.
+#
+CC = gcc88 -Dm88k -ansi -pedantic -Wall -fno-builtin
+AS = as88
diff --git a/ext/systemc/src/sysc/qt/md/m88k.c b/ext/systemc/src/sysc/qt/md/m88k.c
new file mode 100644
index 000000000..f2cef00a0
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/m88k.c
@@ -0,0 +1,111 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+#include <stdarg.h>
+#include "qt.h"
+
+/* Varargs is harder on the m88k. Parameters are saved on the stack as
+ something like (stack grows down to low memory; low at bottom of
+ picture):
+
+ | :
+ | arg8 <-- va_list.__va_stk
+ +---
+ | :
+ +---
+ | arg7
+ | :
+ | iarg0 <-- va_list.__va_reg
+ +---
+ | :
+ | va_list { __va_arg, __va_stk, __va_reg }
+ | :
+ +---
+
+ Here, `va_list.__va_arg' is the number of word-size arguments
+ that have already been skipped. Doubles must be double-arligned.
+
+ What this means for us is that the user's routine needs to be
+ called with an arg list where some of the words in the `__va_stk'
+ part of the parameter list have to be promoted to registers.
+
+ BUG: doubleword register arguments must be double-aligned. If
+ something is passed as an even # arg and used as an odd # arg or
+ vice-versa, the code in the called routine (in the new thread) that
+ decides how to adjust the index will get it wrong, because it will
+ be expect it to be, say, doubleword aligned and it will really be
+ singleword aligned.
+
+ I'm not sure you can solve this without knowing the types of all
+ the arguments. All in all, we never promised varargs would work
+ reliably. */
+
+
+
+#define QUICKTHREADS_VADJ(sp) (((char *)sp) - QUICKTHREADS_VSTKBASE)
+
+/* Always allocate at least enough space for 8 args; waste some space
+ at the base of the stack to ensure the startup routine doesn't read
+ off the end of the stack. */
+
+#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \
+ ((qt_t *)(((char *)(sp)) - 8*4 - QUICKTHREADS_STKROUNDUP(vabytes)))
+
+extern void qt_vstart(void);
+#define QUICKTHREADS_VARGS_MD1(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_1, qt_vstart))
+
+
+ struct qt_t *
+qt_vargs (struct qt_t *qsp, int nbytes, void *vargs,
+ void *pt, qt_function_t *startup,
+ qt_function_t *vuserf, qt_function_t *cleanup)
+{
+ va_list ap;
+ int i;
+ int n; /* Number of words into original arg list. */
+ qt_word_t *sp;
+ int *reg; /* Where to read passed-in-reg args. */
+ int *stk; /* Where to read passed-on-stk args. */
+
+ ap = *(va_list *)vargs;
+ qsp = QUICKTHREADS_VARGS_MD0 (qsp, nbytes);
+ sp = (qt_word_t *)qsp;
+
+ reg = (ap.__va_arg < 8)
+ ? &ap.__va_reg[ap.__va_arg]
+ : 0;
+ stk = &ap.__va_stk[8];
+ n = ap.__va_arg;
+ for (i=0; i<nbytes/sizeof(qt_word_t) && n<8; ++i,++n) {
+ sp[i] = *reg++;
+ }
+ for (; i<nbytes/sizeof(qt_word_t); ++i) {
+ sp[i] = *stk++;
+ }
+
+#ifdef QUICKTHREADS_NDEF
+ for (i=0; i<nbytes/sizeof(qt_word_t); ++i) {
+ sp[i] = (n < 8)
+ ? *reg++
+ : *stk++;
+ ++n;
+ }
+#endif
+
+ QUICKTHREADS_VARGS_MD1 (QUICKTHREADS_VADJ(sp));
+ QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VARGT_INDEX, pt);
+ QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VSTARTUP_INDEX, startup);
+ QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VUSERF_INDEX, vuserf);
+ QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VCLEANUP_INDEX, cleanup);
+ return ((qt_t *)QUICKTHREADS_VADJ(sp));
+}
diff --git a/ext/systemc/src/sysc/qt/md/m88k.h b/ext/systemc/src/sysc/qt/md/m88k.h
new file mode 100644
index 000000000..f9cab5327
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/m88k.h
@@ -0,0 +1,159 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+#ifndef QUICKTHREADS_M88K_H
+#define QUICKTHREADS_M88K_H
+
+typedef unsigned long qt_word_t;
+
+#define QUICKTHREADS_GROW_DOWN
+
+/* Stack layout on the mips:
+
+ Callee-save registers are: $16-$23, $30; $f20-$f30.
+ Also save $31, return pc.
+
+ Non-varargs:
+
+ +---
+ | r30 (fp) on startup === 0
+ | r25
+ | r24
+ | r23
+ | r22
+ | r21
+ | r20
+ | r19
+ | r18
+ | r17 on startup === `only'
+ | r16 on startup === `userf'
+ | r15 on startup === `pt'
+ | r14 on startup === `pu'
+ | r1 on startup === `qt_start'
+ | 0
+ | 0
+ +---
+ | 0
+ | ... (8 regs worth === 32 bytes of homing area)
+ | 0 <--- sp
+ +---
+
+ Conventions for varargs:
+
+ | :
+ | arg8
+ +---
+ | r30 (fp) arg7
+ | r25 arg6
+ | r24 arg5
+ | r23 arg4
+ | r22 arg3
+ | r21 arg2
+ | r20 arg1
+ | r19 arg0
+ | r18
+ | r17 on startup === `startup'
+ | r16 on startup === `vuserf'
+ | r15 on startup === `pt'
+ | r14 on startup === `cleanup'
+ | r1 on startup === `qt_vstart'
+ | 0
+ | 0
+ +---
+ | 0
+ | ... (8 regs worth === 32 bytes of homing area)
+ | 0 <--- sp
+ +---
+
+ */
+
+
+/* Stack must be doubleword aligned. */
+#define QUICKTHREADS_STKALIGN (16) /* Doubleword aligned. */
+
+/* How much space is allocated to hold all the crud for
+ initialization: saved registers plus padding to keep the stack
+ aligned plus 8 words of padding to use as a `homing area' (for
+ r2-r9) when calling helper functions on the stack of the (not yet
+ started) thread. The varargs save area is small because it gets
+ overlapped with the top of the parameter list. In case the
+ parameter list is less than 8 args, QUICKTHREADS_ARGS_MD0 adds some dead
+ space at the top of the stack. */
+
+#define QUICKTHREADS_STKBASE (16*4 + 8*4)
+#define QUICKTHREADS_VSTKBASE (8*4 + 8*4)
+
+
+/* Index of various registers. */
+#define QUICKTHREADS_1 (8+2)
+#define QUICKTHREADS_14 (8+3)
+#define QUICKTHREADS_15 (8+4)
+#define QUICKTHREADS_16 (8+5)
+#define QUICKTHREADS_17 (8+6)
+#define QUICKTHREADS_30 (8+15)
+
+
+/* When a never-before-run thread is restored, the return pc points
+ to a fragment of code that starts the thread running. For
+ non-vargs functions, it sets up arguments and calls the client's
+ `only' function. For varargs functions, the startup code calls the
+ startup, user, and cleanup functions.
+
+ For non-varargs functions, we set the frame pointer to 0 to
+ null-terminate the call chain.
+
+ For varargs functions, the frame pointer register is used to hold
+ one of the arguments, so that all arguments can be laid out in
+ memory by the conventional `qt_vargs' varargs initialization
+ routine.
+
+ The varargs startup routine always reads 8 words of arguments from
+ the stack. If there are less than 8 words of arguments, then the
+ arg list could call off the top of the stack. To prevent fall-off,
+ always allocate 8 words. */
+
+extern void qt_start(void);
+#define QUICKTHREADS_ARGS_MD(sp) \
+ (QUICKTHREADS_SPUT (sp, QUICKTHREADS_1, qt_start), \
+ QUICKTHREADS_SPUT (sp, QUICKTHREADS_30, 0))
+
+
+/* The m88k uses a struct for `va_list', so pass a pointer to the
+ struct. */
+
+typedef void (qt_function_t)(void);
+
+struct qt_t;
+extern struct qt_t *qt_vargs (struct qt_t *sp, int nbytes,
+ void *vargs, void *pt,
+ qt_function_t *startup,
+ qt_function_t *vuserf,
+ qt_function_t *cleanup);
+
+#define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \
+ (qt_vargs (sp, nbytes, &(vargs), pt, (qt_function_t *)startup, \
+ (qt_function_t *)vuserf, (qt_function_t *)cleanup))
+
+
+/* The *index* (positive offset) of where to put each value. */
+#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_17)
+#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_16)
+#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_15)
+#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_14)
+
+#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_14)
+#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_16)
+#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_17)
+#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_15)
+
+#endif /* ndef QUICKTHREADS_M88K_H */
diff --git a/ext/systemc/src/sysc/qt/md/m88k.s b/ext/systemc/src/sysc/qt/md/m88k.s
new file mode 100644
index 000000000..42467e8d5
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/m88k.s
@@ -0,0 +1,132 @@
+/* m88k.s -- assembly support. */
+
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+/* Callee-save r14..r25, r31(sp), r30(fp). r1 === return pc.
+ * Argument registers r2..r9, return value r2..r3.
+ *
+ * On startup, restore regs so retpc === call to a function to start.
+ *
+ * We're going to call a function (r2) from within the context switch
+ * routine. Call it on the new thread's stack on behalf of the old
+ * thread.
+ */
+
+ .globl _qt_block
+ .globl _qt_blocki
+ .globl _qt_abort
+ .globl _qt_start
+ .globl _qt_vstart
+
+ /*
+ ** r2: ptr to function to call once curr is suspended
+ ** and control is on r5's stack.
+ ** r3: 1'th arg to *r2.
+ ** r4: 2'th arg to *r2.
+ ** r5: sp of thread to suspend.
+ **
+ ** The helper routine returns a value that is passed on as the
+ ** return value from the blocking routine. Since we don't
+ ** touch r2 between the helper's return and the end of
+ ** function, we get this behavior for free.
+ **
+ ** Same entry for integer-only and floating-point, since there
+ ** are no separate integer and floating-point registers.
+ **
+ ** Each procedure call sets aside a ``home region'' of 8 regs
+ ** for r2-r9 for varargs. For context switches we don't use
+ ** the ``home region'' for varargs so use it to save regs.
+ ** Allocate 64 bytes of save space -- use 32 bytes of register
+ ** save area passed in to us plus 32 bytes we allcated, use
+ ** the other 32 bytes for save area for a save area to call
+ ** the helper function.
+ */
+_qt_block:
+_qt_blocki:
+ sub r31, r31,64 /* Allocate reg save space. */
+ st r1, r31,8+32 /* Save callee-save registers. */
+ st r14, r31,12+32
+ st.d r15, r31,16+32
+ st.d r17, r31,24+32
+ st.d r19, r31,32+32
+ st.d r21, r31,40+32
+ st.d r23, r31,48+32
+ st r25, r31,56+32
+ st r30, r31,60+32
+
+_qt_abort:
+ addu r14, r31,0 /* Remember old sp. */
+ addu r31, r5,0 /* Set new sp. */
+ jsr.n r2 /* Call helper. */
+ addu r2, r14,0 /* Pass old sp as an arg0 to helper. */
+
+ ld r1, r31,8+32 /* Restore callee-save registers. */
+ ld r14, r31,12+32
+ ld.d r15, r31,16+32
+ ld.d r17, r31,24+32
+ ld.d r19, r31,32+32
+ ld.d r21, r31,40+32
+ ld.d r23, r31,48+32
+ ld r25, r31,56+32
+ ld r30, r31,60+32
+
+ jmp.n r1 /* Return to new thread's caller. */
+ addu r31, r31,64 /* Free register save space. */
+
+
+ /*
+ ** Non-varargs thread startup.
+ ** See `m88k.h' for register use conventions.
+ */
+_qt_start:
+ addu r2, r14,0 /* Set user arg `pu'. */
+ addu r3, r15,0 /* ... user function pt. */
+ jsr.n r17 /* Call `only'. */
+ addu r4, r16,0 /* ... user function userf. */
+
+ bsr _qt_error /* `only' erroniously returned. */
+
+
+ /*
+ ** Varargs thread startup.
+ ** See `m88k.h' for register use conventions.
+ **
+ ** Call the `startup' function with just argument `pt'.
+ ** Then call `vuserf' with 8 register args plus any
+ ** stack args.
+ ** Then call `cleanup' with `pt' and the return value
+ ** from `vuserf'.
+ */
+_qt_vstart:
+ addu r18, r30,0 /* Remember arg7 to `vuserf'. */
+ addu r30, r0,0 /* Null-terminate call chain. */
+
+ jsr.n r17 /* Call `startup'. */
+ addu r2, r15,0 /* `pt' is arg0 to `startup'. */
+
+ addu r2, r19,0 /* Set arg0. */
+ addu r3, r20,0 /* Set arg1. */
+ addu r4, r21,0 /* Set arg2. */
+ addu r5, r22,0 /* Set arg3. */
+ addu r6, r23,0 /* Set arg4. */
+ addu r7, r24,0 /* Set arg5. */
+ addu r8, r25,0 /* Set arg6. */
+ jsr.n r16 /* Call `vuserf'. */
+ addu r9, r18,0 /* Set arg7. */
+
+ addu r3, r2,0 /* Ret. value is arg1 to `cleanup'. */
+ jsr.n r14 /* Call `cleanup'. */
+ addu r2, r15,0 /* `pt' is arg0 to `cleanup'. */
+
+ bsr _qt_error /* `cleanup' erroniously returned. */
diff --git a/ext/systemc/src/sysc/qt/md/m88k_b.s b/ext/systemc/src/sysc/qt/md/m88k_b.s
new file mode 100644
index 000000000..1926e6ae8
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/m88k_b.s
@@ -0,0 +1,117 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+ .text
+ .globl _b_call_reg
+ .globl _b_call_imm
+ .globl _b_add
+ .globl _b_load
+
+_b_null:
+ jmp r1
+
+_b_call_reg:
+ subu r31, r31,8 /* Alloc ret pc save space. */
+ st r1, r31,32 /* Save ret pc. */
+ or.u r3, r0,hi16(_b_null) /* Put call addr in a reg. */
+ or r3, r3,lo16(_b_null)
+ jsr r3
+L0:
+ jsr r3
+ jsr r3
+ jsr r3
+ jsr.n r3
+ subu r2, r2,5 /* Decrement #of iter to go. */
+ bcnd.n gt0,r2,L0
+ jsr r3
+
+ ld r1, r31,32
+ jmp r1
+
+
+_b_call_imm:
+ subu r31, r31,8 /* Alloc ret pc save space. */
+ st r1, r31,32 /* Save ret pc. */
+ bsr _b_null
+L1:
+ bsr _b_null
+ bsr _b_null
+ bsr _b_null
+ bsr.n _b_null
+ subu r2, r2,5 /* Decrement #of iter to go. */
+ bcnd.n gt0,r2,L1
+ bsr _b_null
+
+ ld r1, r31,32
+ jmp r1
+
+_b_add:
+ add r0, r3,r4
+L2:
+ add r3, r4,r5
+ add r4, r5,r6
+ add r5, r6,r7
+ add r8, r9,r0
+ add r0, r3,r4
+ add r3, r4,r5
+ add r4, r5,r6
+ add r5, r6,r7
+ add r8, r9,r0
+
+ add r0, r3,r4
+ add r3, r4,r5
+ add r4, r5,r6
+ add r5, r6,r7
+ add r8, r9,r0
+ add r0, r3,r4
+ add r3, r4,r5
+ add r4, r5,r6
+ add r5, r6,r7
+ add r8, r9,r0
+
+ subu r2, r2,20 /* Decrement #of iter to go. */
+ bcnd.n gt0,r2,L2
+ add r0, r3,r4
+
+ jmp r1
+
+
+_b_load:
+ ld r0, r31,0
+L3:
+ ld r3, r31,4
+ ld r4, r31,8
+ ld r5, r31,12
+ ld r6, r31,16
+ ld r0, r31,0
+ ld r3, r31,4
+ ld r4, r31,8
+ ld r5, r31,12
+ ld r6, r31,16
+
+ ld r0, r31,0
+ ld r3, r31,4
+ ld r4, r31,8
+ ld r5, r31,12
+ ld r6, r31,16
+ ld r0, r31,0
+ ld r3, r31,4
+ ld r4, r31,8
+ ld r5, r31,12
+ ld r6, r31,16
+
+ subu r2, r2,20 /* Decrement #of iter to go. */
+ bcnd.n gt0,r2,L3
+ ld r0, r31,0
+
+ jmp r1
diff --git a/ext/systemc/src/sysc/qt/md/mips-irix5.s b/ext/systemc/src/sysc/qt/md/mips-irix5.s
new file mode 100644
index 000000000..234a953ed
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/mips-irix5.s
@@ -0,0 +1,182 @@
+/* mips.s -- assembly support. */
+
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+/* Callee-save $16-$23, $30-$31.
+ *
+ * $25 is used as a procedure value pointer, used to discover constants
+ * in a callee. Thus, each caller here sets $25 before the call.
+ *
+ * On startup, restore regs so retpc === call to a function to start.
+ * We're going to call a function ($4) from within this routine.
+ * We're passing 3 args, therefore need to allocate 12 extra bytes on
+ * the stack for a save area. The start routine needs a like 16-byte
+ * save area. Must be doubleword aligned (_mips r3000 risc
+ * architecture_, gerry kane, pg d-23).
+ */
+
+/*
+ * Modified by Assar Westerlund <assar@sics.se> to support Irix 5.x
+ * calling conventions for dynamically-linked code.
+ */
+
+ /* Make this position-independent code. */
+ .option pic2
+
+ .globl qt_block
+ .globl qt_blocki
+ .globl qt_abort
+ .globl qt_start
+ .globl qt_vstart
+
+ /*
+ ** $4: ptr to function to call once curr is suspended
+ ** and control is on $7's stack.
+ ** $5: 1'th arg to $4.
+ ** $6: 2'th arg to $4
+ ** $7: sp of thread to suspend.
+ **
+ ** Totally gross hack: The MIPS calling convention reserves
+ ** 4 words on the stack for a0..a3. This routine "ought" to
+ ** allocate space for callee-save registers plus 4 words for
+ ** the helper function, but instead we use the 4 words
+ ** provided by the function that called us (we don't need to
+ ** save our argument registers). So what *appears* to be
+ ** allocating only 40 bytes is actually allocating 56, by
+ ** using the caller's 16 bytes.
+ **
+ ** The helper routine returns a value that is passed on as the
+ ** return value from the blocking routine. Since we don't
+ ** touch $2 between the helper's return and the end of
+ ** function, we get this behavior for free.
+ */
+qt_blocki:
+ sub $sp,$sp,40 /* Allocate reg save space. */
+ sw $16, 0+16($sp)
+ sw $17, 4+16($sp)
+ sw $18, 8+16($sp)
+ sw $19,12+16($sp)
+ sw $20,16+16($sp)
+ sw $21,20+16($sp)
+ sw $22,24+16($sp)
+ sw $23,28+16($sp)
+ sw $30,32+16($sp)
+ sw $31,36+16($sp)
+ add $2, $sp,$0 /* $2 <= old sp to pass to func@$4. */
+qt_abort:
+ add $sp, $7,$0 /* $sp <= new sp. */
+ .set noreorder
+ add $25, $4,$0 /* Set helper function procedure value. */
+ jal $31,$25 /* Call helper func@$4 . */
+ add $4, $2,$0 /* $a0 <= pass old sp as a parameter. */
+ .set reorder
+ lw $31,36+16($sp) /* Restore callee-save regs... */
+ lw $30,32+16($sp)
+ lw $23,28+16($sp)
+ lw $22,24+16($sp)
+ lw $21,20+16($sp)
+ lw $20,16+16($sp)
+ lw $19,12+16($sp)
+ lw $18, 8+16($sp)
+ lw $17, 4+16($sp)
+ lw $16, 0+16($sp) /* Restore callee-save */
+
+ add $sp,$sp,40 /* Deallocate reg save space. */
+ j $31 /* Return to caller. */
+
+ /*
+ ** Non-varargs thread startup.
+ ** Note: originally, 56 bytes were allocated on the stack.
+ ** The thread restore routine (_blocki/_abort) removed 40
+ ** of them, which means there is still 16 bytes for the
+ ** argument area required by the MIPS calling convention.
+ */
+qt_start:
+ add $4, $16,$0 /* Load up user function pu. */
+ add $5, $17,$0 /* ... user function pt. */
+ add $6, $18,$0 /* ... user function userf. */
+ add $25, $19,$0 /* Set `only' procedure value. */
+ jal $31,$25 /* Call `only'. */
+ la $25,qt_error /* Set `qt_error' procedure value. */
+ j $25
+
+
+ /*
+ ** Save calle-save floating-point regs $f20-$f30
+ ** See comment in `qt_block' about calling conventinos and
+ ** reserved space. Use the same trick here, but here we
+ ** actually have to allocate all the bytes since we have to
+ ** leave 4 words leftover for `qt_blocki'.
+ **
+ ** Return value from `qt_block' is the same as the return from
+ ** `qt_blocki'. We get that for free since we don't touch $2
+ ** between the return from `qt_blocki' and the return from
+ ** `qt_block'.
+ */
+qt_block:
+ sub $sp, $sp,56 /* 6 8-byte regs, saved ret pc, aligned. */
+ swc1 $f20, 0+16($sp)
+ swc1 $f22, 8+16($sp)
+ swc1 $f24, 16+16($sp)
+ swc1 $f26, 24+16($sp)
+ swc1 $f28, 32+16($sp)
+ swc1 $f30, 40+16($sp)
+ sw $31, 48+16($sp)
+ jal qt_blocki
+ lwc1 $f20, 0+16($sp)
+ lwc1 $f22, 8+16($sp)
+ lwc1 $f24, 16+16($sp)
+ lwc1 $f26, 24+16($sp)
+ lwc1 $f28, 32+16($sp)
+ lwc1 $f30, 40+16($sp)
+ lw $31, 48+16($sp)
+ add $sp, $sp,56
+ j $31
+
+
+ /*
+ ** First, call `startup' with the `pt' argument.
+ **
+ ** Next, call the user's function with all arguments.
+ ** Note that we don't know whether args were passed in
+ ** integer regs, fp regs, or on the stack (See Gerry Kane
+ ** "MIPS R2000 RISC Architecture" pg D-22), so we reload
+ ** all the registers, possibly with garbage arguments.
+ **
+ ** Finally, call `cleanup' with the `pt' argument and with
+ ** the return value from the user's function. It is an error
+ ** for `cleanup' to return.
+ */
+qt_vstart:
+ add $4, $17,$0 /* `pt' is arg0 to `startup'. */
+ add $25, $18,$0 /* Set `startup' procedure value. */
+ jal $31, $25 /* Call `startup'. */
+
+ add $sp, $sp,16 /* Free extra save space. */
+ lw $4, 0($sp) /* Load up args. */
+ lw $5, 4($sp)
+ lw $6, 8($sp)
+ lw $7, 12($sp)
+ lwc1 $f12, 0($sp) /* Load up fp args. */
+ lwc1 $f14, 8($sp)
+ add $25, $19,$0 /* Set `userf' procedure value. */
+ jal $31,$25 /* Call `userf'. */
+
+ add $4, $17,$0 /* `pt' is arg0 to `cleanup'. */
+ add $5, $2,$0 /* Ret. val is arg1 to `cleanup'. */
+ add $25, $16,$0 /* Set `cleanup' procedure value. */
+ jal $31, $25 /* Call `cleanup'. */
+
+ la $25,qt_error /* Set `qt_error' procedure value. */
+ j $25
diff --git a/ext/systemc/src/sysc/qt/md/mips.h b/ext/systemc/src/sysc/qt/md/mips.h
new file mode 100644
index 000000000..14d109461
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/mips.h
@@ -0,0 +1,134 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+#ifndef QUICKTHREADS_MIPS_H
+#define QUICKTHREADS_MIPS_H
+
+typedef unsigned long qt_word_t;
+
+#define QUICKTHREADS_GROW_DOWN
+
+/* Stack layout on the mips:
+
+ Callee-save registers are: $16-$23, $30; $f20-$f30.
+ Also save $31, return pc.
+
+ Non-varargs:
+
+ +---
+ | $f30 The first clump is only saved if `qt_block'
+ | $f28 is called, in which case it saves the fp regs
+ | $f26 then calls `qt_blocki' to save the int regs.
+ | $f24
+ | $f22
+ | $f20
+ | $31 === return pc in `qt_block'
+ +---
+ | $31 === return pc; on startup == qt_start
+ | $30
+ | $23
+ | $22
+ | $21
+ | $20
+ | $19 on startup === only
+ | $18 on startup === $a2 === userf
+ | $17 on startup === $a1 === pt
+ | $16 on startup === $a0 === pu
+ | <a3> save area req'd by MIPS calling convention
+ | <a2> save area req'd by MIPS calling convention
+ | <a1> save area req'd by MIPS calling convention
+ | <a0> save area req'd by MIPS calling convention <--- sp
+ +---
+
+ Conventions for varargs:
+
+ | args ...
+ +---
+ | :
+ | :
+ | $21
+ | $20
+ | $19 on startup === `userf'
+ | $18 on startup === `startup'
+ | $17 on startup === `pt'
+ | $16 on startup === `cleanup'
+ | <a3>
+ | <a2>
+ | <a1>
+ | <a0> <--- sp
+ +---
+
+ Note: if we wanted to, we could muck about and try to get the 4
+ argument registers loaded in to, e.g., $22, $23, $30, and $31,
+ and the return pc in, say, $20. Then, the first 4 args would
+ not need to be loaded from memory, they could just use
+ register-to-register copies. */
+
+
+/* Stack must be doubleword aligned. */
+#define QUICKTHREADS_STKALIGN (8) /* Doubleword aligned. */
+
+/* How much space is allocated to hold all the crud for
+ initialization: $16-$23, $30, $31. Just do an integer restore,
+ no need to restore floating-point. Four words are needed for the
+ argument save area for the helper function that will be called for
+ the old thread, just before the new thread starts to run. */
+
+#define QUICKTHREADS_STKBASE (14 * 4)
+#define QUICKTHREADS_VSTKBASE QUICKTHREADS_STKBASE
+
+
+/* Offsets of various registers. */
+#define QUICKTHREADS_31 (9+4)
+#define QUICKTHREADS_19 (3+4)
+#define QUICKTHREADS_18 (2+4)
+#define QUICKTHREADS_17 (1+4)
+#define QUICKTHREADS_16 (0+4)
+
+
+/* When a never-before-run thread is restored, the return pc points
+ to a fragment of code that starts the thread running. For
+ non-vargs functions, it just calls the client's `only' function.
+ For varargs functions, it calls the startup, user, and cleanup
+ functions.
+
+ The varargs startup routine always reads 4 words of arguments from
+ the stack. If there are less than 4 words of arguments, then the
+ startup routine can read off the top of the stack. To prevent
+ errors we always allocate 4 words. If there are more than 3 words
+ of arguments, the 4 preallocated words are simply wasted. */
+
+extern void qt_start(void);
+#define QUICKTHREADS_ARGS_MD(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_31, qt_start))
+
+#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \
+ ((qt_t *)(((char *)(sp)) - 4*4 - QUICKTHREADS_STKROUNDUP(vabytes)))
+
+extern void qt_vstart(void);
+#define QUICKTHREADS_VARGS_MD1(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_31, qt_vstart))
+
+#define QUICKTHREADS_VARGS_DEFAULT
+
+
+/* The *index* (positive offset) of where to put each value. */
+#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_19)
+#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_18)
+#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_17)
+#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_16)
+
+#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_16)
+#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_19)
+#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_18)
+#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_17)
+
+#endif /* ndef QUICKTHREADS_MIPS_H */
diff --git a/ext/systemc/src/sysc/qt/md/mips.s b/ext/systemc/src/sysc/qt/md/mips.s
new file mode 100644
index 000000000..b074b98dc
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/mips.s
@@ -0,0 +1,164 @@
+/* mips.s -- assembly support. */
+
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+/* Callee-save $16-$23, $30-$31.
+ *
+ * On startup, restore regs so retpc === call to a function to start.
+ * We're going to call a function ($4) from within this routine.
+ * We're passing 3 args, therefore need to allocate 12 extra bytes on
+ * the stack for a save area. The start routine needs a like 16-byte
+ * save area. Must be doubleword aligned (_mips r3000 risc
+ * architecture_, gerry kane, pg d-23).
+ */
+
+ .globl qt_block
+ .globl qt_blocki
+ .globl qt_abort
+ .globl qt_start
+ .globl qt_vstart
+
+ /*
+ ** $4: ptr to function to call once curr is suspended
+ ** and control is on $7's stack.
+ ** $5: 1'th arg to $4.
+ ** $6: 2'th arg to $4
+ ** $7: sp of thread to suspend.
+ **
+ ** Totally gross hack: The MIPS calling convention reserves
+ ** 4 words on the stack for a0..a3. This routine "ought" to
+ ** allocate space for callee-save registers plus 4 words for
+ ** the helper function, but instead we use the 4 words
+ ** provided by the function that called us (we don't need to
+ ** save our argument registers). So what *appears* to be
+ ** allocating only 40 bytes is actually allocating 56, by
+ ** using the caller's 16 bytes.
+ **
+ ** The helper routine returns a value that is passed on as the
+ ** return value from the blocking routine. Since we don't
+ ** touch $2 between the helper's return and the end of
+ ** function, we get this behavior for free.
+ */
+qt_blocki:
+ sub $sp,$sp,40 /* Allocate reg save space. */
+ sw $16, 0+16($sp)
+ sw $17, 4+16($sp)
+ sw $18, 8+16($sp)
+ sw $19,12+16($sp)
+ sw $20,16+16($sp)
+ sw $21,20+16($sp)
+ sw $22,24+16($sp)
+ sw $23,28+16($sp)
+ sw $30,32+16($sp)
+ sw $31,36+16($sp)
+ add $2, $sp,$0 /* $2 <= old sp to pass to func@$4. */
+qt_abort:
+ add $sp, $7,$0 /* $sp <= new sp. */
+ .set noreorder
+ jal $31,$4 /* Call helper func@$4 . */
+ add $4, $2,$0 /* $a0 <= pass old sp as a parameter. */
+ .set reorder
+ lw $31,36+16($sp) /* Restore callee-save regs... */
+ lw $30,32+16($sp)
+ lw $23,28+16($sp)
+ lw $22,24+16($sp)
+ lw $21,20+16($sp)
+ lw $20,16+16($sp)
+ lw $19,12+16($sp)
+ lw $18, 8+16($sp)
+ lw $17, 4+16($sp)
+ lw $16, 0+16($sp) /* Restore callee-save */
+
+ add $sp,$sp,40 /* Deallocate reg save space. */
+ j $31 /* Return to caller. */
+
+ /*
+ ** Non-varargs thread startup.
+ ** Note: originally, 56 bytes were allocated on the stack.
+ ** The thread restore routine (_blocki/_abort) removed 40
+ ** of them, which means there is still 16 bytes for the
+ ** argument area required by the MIPS calling convention.
+ */
+qt_start:
+ add $4, $16,$0 /* Load up user function pu. */
+ add $5, $17,$0 /* ... user function pt. */
+ add $6, $18,$0 /* ... user function userf. */
+ jal $31,$19 /* Call `only'. */
+ j qt_error
+
+
+ /*
+ ** Save calle-save floating-point regs $f20-$f30
+ ** See comment in `qt_block' about calling conventinos and
+ ** reserved space. Use the same trick here, but here we
+ ** actually have to allocate all the bytes since we have to
+ ** leave 4 words leftover for `qt_blocki'.
+ **
+ ** Return value from `qt_block' is the same as the return from
+ ** `qt_blocki'. We get that for free since we don't touch $2
+ ** between the return from `qt_blocki' and the return from
+ ** `qt_block'.
+ */
+qt_block:
+ sub $sp, $sp,56 /* 6 8-byte regs, saved ret pc, aligned. */
+ swc1 $f20, 0+16($sp)
+ swc1 $f22, 8+16($sp)
+ swc1 $f24, 16+16($sp)
+ swc1 $f26, 24+16($sp)
+ swc1 $f28, 32+16($sp)
+ swc1 $f30, 40+16($sp)
+ sw $31, 48+16($sp)
+ jal qt_blocki
+ lwc1 $f20, 0+16($sp)
+ lwc1 $f22, 8+16($sp)
+ lwc1 $f24, 16+16($sp)
+ lwc1 $f26, 24+16($sp)
+ lwc1 $f28, 32+16($sp)
+ lwc1 $f30, 40+16($sp)
+ lw $31, 48+16($sp)
+ add $sp, $sp,56
+ j $31
+
+
+ /*
+ ** First, call `startup' with the `pt' argument.
+ **
+ ** Next, call the user's function with all arguments.
+ ** Note that we don't know whether args were passed in
+ ** integer regs, fp regs, or on the stack (See Gerry Kane
+ ** "MIPS R2000 RISC Architecture" pg D-22), so we reload
+ ** all the registers, possibly with garbage arguments.
+ **
+ ** Finally, call `cleanup' with the `pt' argument and with
+ ** the return value from the user's function. It is an error
+ ** for `cleanup' to return.
+ */
+qt_vstart:
+ add $4, $17,$0 /* `pt' is arg0 to `startup'. */
+ jal $31, $18 /* Call `startup'. */
+
+ add $sp, $sp,16 /* Free extra save space. */
+ lw $4, 0($sp) /* Load up args. */
+ lw $5, 4($sp)
+ lw $6, 8($sp)
+ lw $7, 12($sp)
+ lwc1 $f12, 0($sp) /* Load up fp args. */
+ lwc1 $f14, 8($sp)
+ jal $31,$19 /* Call `userf'. */
+
+ add $4, $17,$0 /* `pt' is arg0 to `cleanup'. */
+ add $5, $2,$0 /* Ret. val is arg1 to `cleanup'. */
+ jal $31, $16 /* Call `cleanup'. */
+
+ j qt_error
diff --git a/ext/systemc/src/sysc/qt/md/mips_b.s b/ext/systemc/src/sysc/qt/md/mips_b.s
new file mode 100644
index 000000000..5b3740843
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/mips_b.s
@@ -0,0 +1,99 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+ .globl b_call_reg
+ .globl b_call_imm
+ .globl b_add
+ .globl b_load
+
+ .ent b_null
+b_null:
+ j $31
+ .end b_null
+
+ .ent b_call_reg
+b_call_reg:
+ la $5,b_null
+ add $6, $31,0
+$L0:
+ jal $5
+ jal $5
+ jal $5
+ jal $5
+ jal $5
+
+ sub $4, $4,5
+ bgtz $4,$L0
+ j $6
+ .end
+
+
+ .ent b_call_imm
+b_call_imm:
+ add $6, $31,0
+$L1:
+ jal b_null
+ jal b_null
+ jal b_null
+ jal b_null
+ jal b_null
+
+ sub $4, $4,5
+ bgtz $4,$L1
+ j $6
+ .end
+
+
+ .ent b_add
+b_add:
+ add $5, $0,$4
+ add $6, $0,$4
+ add $7, $0,$4
+ add $8, $0,$4
+$L2:
+ sub $4, $4,5
+ sub $5, $5,5
+ sub $6, $6,5
+ sub $7, $7,5
+ sub $8, $8,5
+
+ sub $4, $4,5
+ sub $5, $5,5
+ sub $6, $6,5
+ sub $7, $7,5
+ sub $8, $8,5
+
+ bgtz $4,$L2
+ j $31
+ .end
+
+
+ .ent b_load
+b_load:
+$L3:
+ ld $0, 0($sp)
+ ld $0, 4($sp)
+ ld $0, 8($sp)
+ ld $0, 12($sp)
+ ld $0, 16($sp)
+
+ ld $0, 20($sp)
+ ld $0, 24($sp)
+ ld $0, 28($sp)
+ ld $0, 32($sp)
+ ld $0, 36($sp)
+
+ sub $4, $4,10
+ bgtz $4,$L3
+ j $31
+ .end
diff --git a/ext/systemc/src/sysc/qt/md/null.README b/ext/systemc/src/sysc/qt/md/null.README
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/null.README
diff --git a/ext/systemc/src/sysc/qt/md/null.c b/ext/systemc/src/sysc/qt/md/null.c
new file mode 100644
index 000000000..db1a593ed
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/null.c
@@ -0,0 +1,14 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+char const qtmd_rcsid[] = "$Header: /Users/acg/CVSROOT/systemc-2.3/src/sysc/qt/md/null.c,v 1.1.1.1 2006/12/15 20:20:06 acg Exp $";
diff --git a/ext/systemc/src/sysc/qt/md/null.s b/ext/systemc/src/sysc/qt/md/null.s
new file mode 100644
index 000000000..8a2361f9e
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/null.s
@@ -0,0 +1,12 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
diff --git a/ext/systemc/src/sysc/qt/md/powerpc.README b/ext/systemc/src/sysc/qt/md/powerpc.README
new file mode 100644
index 000000000..b98da8b27
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/powerpc.README
@@ -0,0 +1,27 @@
+
+PowerPC assembly support
+
+
+1) MacOS X, Darwin, MKLinux and other systems based on Mach kernel ABI:
+
+ - Configuration command: ./config powerpc-darwin
+
+ - See documentation inside powerpc_mach.h, powerpc_mach.s, powerpc.c.
+
+
+2) LinuxPPC, and other systems based on System V ABI:
+
+ - Configuration command: ./config powerpc
+
+ - See documentation inside powerpc_sys5.h, powerpc_sys5.s, powerpc.c.
+
+
+Marco Bucci <marco.bucci@inwind.it>
+December 2002
+
+
+ * This software is largely based on the original PowerPC-Linux porting
+ * developed by Ken Aaker <kenaaker@silverbacksystems.com>
+ *
+ * Marco Bucci <marco.bucci@inwind.it>
+ * December 2002
diff --git a/ext/systemc/src/sysc/qt/md/powerpc.c b/ext/systemc/src/sysc/qt/md/powerpc.c
new file mode 100644
index 000000000..fb374f3f2
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/powerpc.c
@@ -0,0 +1,69 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+
+#include <stdarg.h>
+#include "qt.h"
+
+// This static is used to find the end of the stack for variable
+
+static void *qt_sp_bottom_save;
+
+/* We actually don't know how the compiler accomodates arguments in the
+ * va_list. In some implementation (e.g. Linux PPC) we cannot scan the
+ * list as an array. To avoid this problem, this version of "qt_varg",
+ * retrieves arguments by means of the standard "va_arg" macro defined
+ * in stdargs.h.
+ *
+ * Notice that we still suppose that the number of arguments is given
+ * by nbytes/sizeof(qt_word_t) and we load the stack of "qt_vstart"
+ * assuming that all parameters are alligned to the size of qt_word_t.
+ *
+ * Marco Bucci <marco.bucci@inwind.it>
+ * December 2002
+ */
+
+/*
+
+qt_t *qt_vargs (qt_t *sp, int nbytes, void *vargs,
+ void *pt, qt_startup_t *startup,
+ qt_vuserf_t *vuserf, qt_cleanup_t *cleanup)
+
+*/
+
+ qt_t *
+qt_vargs_stdarg (qt_t *sp, int nbytes, va_list vargs,
+ void *pt, qt_startup_t *startup,
+ qt_vuserf_t *vuserf, qt_cleanup_t *cleanup)
+
+
+
+{
+ int i;
+ qt_word_t arg;
+
+ sp = QUICKTHREADS_VARGS_MD0 (sp, nbytes);
+
+ for ( i=0;i<(int)(nbytes/sizeof(qt_word_t)); i++)
+ {
+ arg = va_arg(vargs, qt_word_t);
+ QUICKTHREADS_SPUT (QUICKTHREADS_VARGS_ADJUST(sp), i, arg);
+ }
+
+ QUICKTHREADS_VARGS_MD1 (QUICKTHREADS_VADJ(sp));
+ QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VARGT_INDEX, pt);
+ QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VSTARTUP_INDEX, startup);
+ QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VUSERF_INDEX, vuserf);
+ QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VCLEANUP_INDEX, cleanup);
+ return ((qt_t *)QUICKTHREADS_VADJ(sp));
+}
diff --git a/ext/systemc/src/sysc/qt/md/powerpc_mach.h b/ext/systemc/src/sysc/qt/md/powerpc_mach.h
new file mode 100644
index 000000000..677808c5c
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/powerpc_mach.h
@@ -0,0 +1,611 @@
+/*
+ + * QuickThreads -- Threads-building toolkit.
+ + * Copyright (c) 1993 by David Keppel
+ + *
+ + * Permission to use, copy, modify and distribute this software and
+ + * its documentation for any purpose and without fee is hereby
+ + * granted, provided that the above copyright notice and this notice
+ + * appear in all copies. This software is provided as a
+ + * proof-of-concept and for demonstration purposes; there is no
+ + * representation about the suitability of this software for any
+ + * purpose.
+ + *
+
+ + * PowerPC-Mach thread switching module.
+ + *
+ + * This software is largely based on the original PowerPC-Linux porting
+ + * developed by Ken Aaker <kenaaker@silverbacksystems.com>
+ + *
+ + * Marco Bucci <marco.bucci@inwind.it>
+ + * December 2002
+ + *
+ + */
+
+
+#ifndef QUICKTHREADS_POWERPC_H
+#define QUICKTHREADS_POWERPC_H
+
+
+/*****************************************************************************
+ *
+ * DESCRIPTION
+ *
+ * This is the QuickThreads switching module implementation for PowerPC
+ * running under Mach kernel. It was developed and tested under MacOS X, that
+ * is under Darwin (the UNIX-BSD fundation of MacOS X).
+ *
+ * Notice that the Mach PowerPC ABI (Application Binary Interface) [1] is
+ * not the same than System V ABI [2] used by most of the LINUX PowerPC
+ * implementations.
+ *
+ * IMPLEMENTATION NOTES
+ *
+ * 1) Porting on System V ABI
+ * Excluding the variant argument calling convention, Mach and System V ABI
+ * are enough similar and it could be possible to use some simple macro, to
+ * adapt the code for both the ABIs. Actually, the only relevant difference
+ * is in the linkage area structure and in the position where the Link and
+ * the Condition registers are saved. As to the calling conventions, there
+ * are differences with floating points argument passing and with variant
+ * argument lists. Notice that, on Mach, the caller's stack frame allocates
+ * space to hold all arguments ([1] p.51), while on System V, the caller's
+ * stack frame allocates space to hold just the arguments that don't fit into
+ * registers ([2] p.3.18).
+ *
+ * 2) Variant argument list implementation
+ * Variant argument calling on a RISC machine is not easy to implement since
+ * parameters are passed via registers instead of via stack. In a general
+ * variant argument implementation, the caller's stack must map the whole
+ * parameter list following the rules related to the use of the GPR and FPR
+ * parameter registers and the stack alignment ([1] p.54).
+ * This implementation is quite simple and not general. It works under the
+ * hypothesis that arguments are 4-bytes aligned integers.
+ *
+ * 3) This heather file organisation
+ * I preferred to not make confusion between macros that are needed (i.e.
+ * directly used) by QuickThreads and internal "implementation" macros. You
+ * will find QuickThreds macros in the end of this header. Sometime they just
+ * refer to an analogous "internal" macro. On the top, there are the macros
+ * that I used to make more clean (I hope) the implementation. I could include
+ * some system heather (as to stack layout definitions, prologs and epilogs,
+ * etc.), but I preferred to have a self-contained heather in order to make
+ * all more clear for mantaining and for possible porting on another ABI.
+ *
+ *
+ * REFERENCES
+ *
+ * [1] - Mach-O Runtime Architecture
+ * Runtime Concepts and Conventions for Mac OS X Programs
+ * Preliminary July 2002
+ *
+ * [2] - SYSTEM V APPLICATION BINARY INTERFACE
+ * PowerPC Processor Supplement
+ * September 1995
+ *
+ * On MacOS X, more documentation is available by installing the "Developer
+ * Tools". Useful macros and documentation can be found in the system headers
+ * files such as asm.h, asm_help.h etc. (see /usr/architecture/ppc/ or
+ * /System/Library/Frameworks/Kernel.framework/Headers/architecture/ppc/).
+
+ *****************************************************************************/
+
+/*****************************************************************************
+ *
+ * PowerPC Mach-O Stack frame (see [1])
+ *
+
+ ................
+ + +
+ | | reserved
+ + CALLER'S LINKAGE AREA +
+ | | Caller's LR
+ + +
+ | | Caller's CR
+ + +
+ backchain -> | | Caller's backchain
+ +==========================+
+ | | FPR31
+ + FPR SAVE AREA +
+ ..............
+ + +
+ | | FPRn
+ +--------------------------+
+ | | GPR31
+ + GPR SAVE AREA +
+ ..............
+ + +
+ | | GPRn
+ +--------------------------+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ | |
+ + LOCAL VARIABLES AREA +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ | | PAR(n)
+ + +
+ | |
+ + PARAMETER AREA +
+ ..............
+ + for FUTURE call +
+ | | PAR(1)
+ + +
+ SP + 24 -> | | PAR(0)
+ +--------------------------+
+ SP + 20 -> | | Caller's TOC
+ + +
+ SP + 16 -> | | reserved
+ + +
+ SP + 12 -> | | reserved
+ + LINKAGE AREA +
+ SP + 8 -> | | LR callee-save for FUTURE call
+ + +
+ SP + 4 -> | | CR callee-save for FUTURE call
+ + +
+ SP -> | | backchain
+ +==========================+
+ STACK TOP (lower address)
+
+ Stack grows down
+ |
+ V
+ * NOTE:
+ *
+ * 1) Parameter are allocated in the CALLER's parameter area. This area must
+ * be large enough to hold all parameters regardless if they are or not passed
+ * in registers.
+ *
+ * The caller parameter area is used:
+ * - by the caller, to store parameters to the callee that cannot fit in
+ * registers (no more parameter registers are available);
+ * - by the callee, to save parameter registers (for istance because they are
+ * needed for a further call).
+ *
+ * Obviously, the callee saves parameter registers, in the location in which
+ * they are mapped on the caller's stack frame. So, be aware that, if
+ * something else is stored in that location, it could be deleted after a call.
+ *
+ * 2) The callee saves LR and CR in the caller's linkage area. All other
+ * callee's state are saved in its own stack frame.
+ *
+
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Stack initialization for a single argument thread
+ *
+
+
+ top + QUICKTHREADS_STKBASE -> STACK BOTTOM (higher address)
+ +==========================+
+ | |
+ + +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ top + QUICKTHREADS_ONLY_INDEX * 4 -> | only param | PAR(3)
+ + +
+ top + QUICKTHREADS_USER_INDEX * 4 -> | userf param | PAR(2)
+ + +
+ top + QUICKTHREADS_ARGT_INDEX * 4 -> | t param | PAR(1)
+ + +
+ top + QUICKTHREADS_ARGU_INDEX * 4 -> | u param | PAR(0)
+ +--------------------------+
+ | |
+ + +
+ ..............
+ + +
+ top + QUICKTHREADS_RETURN_INDEX * 4 -> | qt_start | LR save
+ + +
+ ..............
+ + +
+ top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE | backchain
+ +==========================+
+ | |
+ + +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ | |
+ + +
+ ..............
+ + +
+ top -> |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain
+ +==========================+
+ STACK TOP (lower address)
+
+ Stack grows down
+ |
+ V
+
+ *****************************************************************************
+ *
+ * Stack initialization for a variant argument thread
+ *
+
+ bottom -> STACK BOTTOM (higher address)
+ +==========================+
+ | |
+ + +
+ ..............
+ + +
+ top + QUICKTHREADS_VSTKBASE -> | arg(0) | PAR(4)
+ +--------------------------+
+ top + QUICKTHREADS_CLEANUP_INDEX * 4 -> | cleanup param | PAR(3)
+ + +
+ top + QUICKTHREADS_USER_INDEX * 4 -> | userf param | PAR(2)
+ + +
+ top + QUICKTHREADS_VSTARTUP_INDEX * 4 ->| startup param | PAR(1)
+ + +
+ top + QUICKTHREADS_ARGT_INDEX * 4 -> | t param | PAR(0)
+ +--------------------------+
+ | |
+ + +
+ ..............
+ + +
+ top + QUICKTHREADS_RETURN_INDEX * 4 -> | qt_start | LR save
+ + +
+ ..............
+ top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE | backchain
+ +==========================+
+ | |
+ + +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ | |
+ + +
+ ..............
+ + +
+ top -> |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain
+ +==========================+
+ STACK TOP (lower address)
+
+ Stack grows down
+ |
+ V
+
+* NOTE:
+*
+* Parameters are passed to "qt_start" or to "qt_vstart" putting them into
+* the stack frames of "qt_start" or "qt_vstart" themselves. This not a
+* conventional parameter passing because parameters should be put into the
+* caller's stack, not into the callee's one. Actually we must consider
+* that as a preload of the parameter area that "qt_start" or "qt_vstart"
+* will use for their own calls.
+* Be aware of the fact that, during a call, the caller's parameter area is,
+* in a certain sense, volatile. In facts, the callee can save parameter
+* registers on the caller's parameter area.
+*
+ *****************************************************************************/
+
+
+/*****************************************************************************
+
+ Define PowerPC Mach-O related macros
+
+ *****************************************************************************/
+
+
+
+typedef unsigned long PPC_W;
+
+/* Stack pointer must always be a multiple of 16 */
+#define PPC_STACK_INCR 16
+#define PPC_ROUND_STACK(length) \
+ (((length)+PPC_STACK_INCR-1) & ~(PPC_STACK_INCR-1))
+
+
+#define PPC_LINKAGE_AREA 24
+#define PPC_CR_SAVE 4
+#define PPC_LR_SAVE 8
+
+#define PPC_PARAM_AREA(n) (4*(n))
+
+#define PPC_GPR_SAVE_AREA (4*19) /* GPR13-GPR31 must be saved */
+#define PPC_FPR_SAVE_AREA (8*18) /* FPR14-FPR31 must be saved */
+
+/* Define parameter offset on the stack.
+ * NOTICE: Parameters are numbered 0, 1, ..., n.
+*/
+#define PPC_PAR(i) (PPC_LINKAGE_AREA+(i)*4)
+
+/*****************************************************************************
+
+ Define stack frames
+
+ *****************************************************************************/
+
+
+/* Define the "qt_blocki" and "qt_abort" stack frame. We use the same stack
+ * frame for both.
+ *
+
+ top + S ->
+ +==========================+
+ top + S - 4 -> | | GPR31
+ + GPR SAVE AREA +
+ ..............
+ + +
+ top + S - 19 * 4 -> | | GPR13
+ +--------------------------+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ | |
+ + +
+ | |
+ + PARAMETER AREA +
+ | |
+ + +
+ top + 24 -> | |
+ +--------------------------+
+ | |
+ + LINKAGE AREA +
+ top -> | |
+ +==========================+
+ */
+
+#define QUICKTHREADS_BLOCKI_FRAME_SIZE \
+ PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)+PPC_GPR_SAVE_AREA)
+
+/* Offset to the base of the GPR save area. Save from GPR13 to GPR31
+ * increasing address.
+ */
+#define QUICKTHREADS_BLOCKI_GPR_SAVE(i) (QUICKTHREADS_BLOCKI_FRAME_SIZE-4+(i-31)*4)
+
+
+
+/* Define the "qt_block" stack frame. Notice that since "qt_black" calls
+ * "qt_blocki", GPR registers are saved into "qt_blocki" stack frame.
+ *
+
+ top + S ->
+ +==========================+
+ top + S - 8 -> | | FPR31
+ + FPR SAVE AREA +
+ ..............
+ + +
+ top + S - 18 * 8 -> | | FPR14
+ +--------------------------+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ | |
+ + +
+ | |
+ + PARAMETER AREA +
+ | |
+ + +
+ top + 24 -> | |
+ +--------------------------+
+ | |
+ + LINKAGE AREA +
+ top -> | |
+ +==========================+
+ */
+
+#define QUICKTHREADS_BLOCK_FRAME_SIZE \
+ PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)+PPC_FPR_SAVE_AREA)
+
+/* Offset to the location where registers are saved.
+ */
+#define QUICKTHREADS_BLOCK_FPR_SAVE(i) (QUICKTHREADS_BLOCK_FRAME_SIZE-8+(i-31)*8)
+
+
+/* Define the "qt_start" frame size. It consists just of the linkage area and
+ * the parameter area.
+ *
+
+ +==========================+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ | | only par
+ + +
+ | | userf par
+ + PARAMETER AREA +
+ | | t par
+ + +
+ top + 24 -> | | u par
+ +--------------------------+
+ | |
+ + LINKAGE AREA +
+ top -> | |
+ +==========================+
+
+ */
+#define QUICKTHREADS_START_FRAME_SIZE PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4))
+
+
+
+/* Define the "qt_vstart" frame. It consists of the linkage area, the fix parameter
+ * area, the variant argument list and a local variable area used in "qt_vstart"
+ * implementation.
+ *
+
+ backchain ->
+ +==========================+
+ backchain - 4 -> | |
+ + LOCAL VARIABLES AREA +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ | | arg(n)
+ + +
+ | |
+ + VARIABLE ARGUMENT LIST +
+ ..............
+ + for userf call +
+ | | arg(1)
+ + +
+ top + 24 + 16 -> | | arg(0)
+ +--------------------------+
+ | | cleanup par
+ + +
+ | | userf par
+ + PARAMETER AREA +
+ | | startup par
+ + +
+ top + 24 -> | | t par
+ +--------------------------+
+ | |
+ + LINKAGE AREA +
+ top -> | |
+ +==========================+
+
+ */
+#define QUICKTHREADS_VARGS_LOCAL_AREA (4*4) /* local variable area */
+
+/* The offset the stack will be moved back before to call "userf(...)".
+ * The linckage area must be moved to be adiacent to the part of the variant
+ * argument list that is in the stack.
+ */
+#define QUICKTHREADS_VARGS_BKOFF PPC_PARAM_AREA(4)
+
+#define QUICKTHREADS_VSTART_FRAME_SIZE(varbytes) \
+ PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)+(varbytes)+ \
+ QUICKTHREADS_VARGS_LOCAL_AREA)
+
+/* Offset to the base of the varian argument list */
+#define QUICKTHREADS_VSTART_LIST_BASE (PPC_LINKAGE_AREA+PPC_PARAM_AREA(4))
+
+
+/* Notice that qt_start and qt_vstart have no parameters, actually their
+ * parameters are written in their stack frame during thread initialization
+ */
+extern void qt_start(void);
+extern void qt_vstart(void);
+
+
+
+/* Offset (in words) of the location where the block routine saves its return
+ * address (i.e. LR). SP points the top of the block routine stack and,
+ * following ppc calling conventions, the return address is saved in the
+ * previous (caller's) stack frame.
+ */
+#define QUICKTHREADS_RETURN_INDEX ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_LR_SAVE)/sizeof(PPC_W))
+
+/* static variable used to get the stack bottom in "VARGS" initialization */
+/* static void *qt_sp_bottom_save; */
+
+#define QUICKTHREADS_ARG_INDEX(i) ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_PAR(i))/sizeof(PPC_W))
+
+/*****************************************************************************
+
+ QuickThreads needed definitions
+
+ *****************************************************************************/
+
+
+#define QUICKTHREADS_GROW_DOWN
+#define QUICKTHREADS_STKALIGN PPC_STACK_INCR
+typedef PPC_W qt_word_t;
+
+
+/* This macro is used by "QUICKTHREADS_ARGS" to initialize a single argument thread.
+ * - set "qt_start" as the "qt_block" or "qt_blocki" return address;
+ * - set the top of the stack backchain;
+ * - set the next backchain (not needed, but just to be "clean").
+ */
+#define QUICKTHREADS_ARGS_MD(sp) \
+ (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_start), \
+ QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \
+ QUICKTHREADS_SPUT (sp, QUICKTHREADS_BLOCKI_FRAME_SIZE/sizeof(PPC_W), \
+ sp+QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE))
+
+
+/* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread.
+ * It returns the pointer to the top of the argument list.
+ * We also use it to get the stack bottom via a static variable. This is a bit
+ * "dirty", it could be better to do it in "qt_vargs", but we don't want change
+ * anything out of this file.
+ * We need the stack bottom to allocate a local variable area used by
+ * "qt_vstart".
+ */
+#define QUICKTHREADS_VARGS_MD0(sp, varbytes) \
+ ((qt_sp_bottom_save = sp), \
+ ((qt_t *)(((char *)(sp)) - \
+ (QUICKTHREADS_VSTART_FRAME_SIZE(varbytes)-QUICKTHREADS_VSTART_LIST_BASE))))
+
+
+/* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread.
+ * - set "qt_start" as the "qt_block" or "qt_blocki" return address;
+ * - set the top of the stackback chain;
+ * - set the next backchain (it points the stack botton).
+ */
+#define QUICKTHREADS_VARGS_MD1(sp) \
+ (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_vstart), \
+ QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \
+ QUICKTHREADS_SPUT (sp, (QUICKTHREADS_BLOCKI_FRAME_SIZE)/sizeof(PPC_W), \
+ qt_sp_bottom_save))
+
+
+/* Activate "qt_vargs" as the initialization routine for the variant
+ * argument threads
+ */
+#define QUICKTHREADS_VARGS_DEFAULT
+
+/* Override "qt_vargs" with "qt_vargs_stdarg".
+ * On LinuxPPC "qt_vargs" doesn't work, "qt_vargs_stdarg" uses a more
+ * standard way to retrieve arguments from the variant list.
+ */
+#define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \
+ ((qt_t *)qt_vargs_stdarg (sp, nbytes, vargs, pt, startup, vuserf, cleanup))
+
+
+/* This macro is used by "QUICKTHREADS_ADJ(sp)" to get the stack top form the stack
+ * bottom during a single argument thread initialization.
+ * It is the space we need to allocate for a single argument thread: the stack
+ * frame for the block routine ("qt_block" or "qt_blocki") and for "qt_start".
+ */
+#define QUICKTHREADS_STKBASE \
+ (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE)
+
+/* This macro is used by "QUICKTHREADS_VADJ(sp)" to get the stack top from the base
+ * of the variant argument list during a variant argument thread initialization.
+ */
+#define QUICKTHREADS_VSTKBASE (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_VSTART_LIST_BASE)
+
+/* The *index* (positive offset) of where to put each value. */
+
+#define QUICKTHREADS_ARGU_INDEX QUICKTHREADS_ARG_INDEX(0)
+#define QUICKTHREADS_ARGT_INDEX QUICKTHREADS_ARG_INDEX(1)
+#define QUICKTHREADS_USER_INDEX QUICKTHREADS_ARG_INDEX(2)
+#define QUICKTHREADS_ONLY_INDEX QUICKTHREADS_ARG_INDEX(3)
+
+
+#define QUICKTHREADS_VARGT_INDEX QUICKTHREADS_ARG_INDEX(0)
+#define QUICKTHREADS_VSTARTUP_INDEX QUICKTHREADS_ARG_INDEX(1)
+#define QUICKTHREADS_VUSERF_INDEX QUICKTHREADS_ARG_INDEX(2)
+#define QUICKTHREADS_VCLEANUP_INDEX QUICKTHREADS_ARG_INDEX(3)
+
+#endif /* ndef QUICKTHREADS_POWERPC_H */
+
diff --git a/ext/systemc/src/sysc/qt/md/powerpc_mach.s b/ext/systemc/src/sysc/qt/md/powerpc_mach.s
new file mode 100644
index 000000000..63414b05d
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/powerpc_mach.s
@@ -0,0 +1,641 @@
+/* powerpc_mach.s -- assembly support. */
+
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+
+
+ * PowerPC-Mach thread switching module.
+ * Darwin (MacOS X) assembly
+ *
+ * NOTICE: Syntax for register names is not the GNU one. Register are
+ * named "rx" and "fx", not "%rx" and "%fx" as usual for the GNU "as" tool.
+ * Darwin "as" tool is based on GNU "as" but follows the "official" PowerPC
+ * syntax.
+ *
+ *
+ * This software is largely based on the original PowerPC-Linux porting
+ * developed by Ken Aaker <kenaaker@silverbacksystems.com>
+ *
+ * Marco Bucci <marco.bucci@inwind.it>
+ * December 2002
+ *
+ */
+
+
+/*
+ *
+ * PowerPC Register convections:
+ *
+ * r0 volatile
+ * r1 SP
+ * r2 system reserved
+ * r3-r4 volatile for parameter passing and function return
+ * r5-r10 volatile for parameter passing
+ * r11-r12 volatile
+ * r13-r14 non volatile registers
+ * f0 volatile
+ * f1 volatile for parameter passing and function return
+ * f2-f13 volatile for parameter passing
+ * f14-f31 non volatile
+ *
+ * cr2-cr4 non volatile
+ *
+ *
+ * See on the heather file for more documentation.
+ *
+ *
+ *
+ * IMPLEMENTATION NOTES
+ *
+ *
+ * 1) Condition register saving
+ * On most machines, the condition code register is caller-save.
+ * On the PPC, the condition code register is callee-save, so the
+ * thread context switch must preserve it.
+ *
+ *
+ * 2) Floating point registers saving
+ * On resuming a thread, floating point registers are or not restored just
+ * depending on which block routine suspended the thread (i.e. regardless
+ * whether "qt_block", "qt_blocki" or "qt_abort" is used to resume it).
+ * This behaviour is obtained by implementing "qt_block" by means af a nested
+ * call to "qt_blocki". As a result, the blocking of a thread always goes
+ * and returns through "qt_blocki and, if a thread was blocked by "qt_block",
+ * its execution resumes from the floating point restoring code on exit
+ * of "qt_block".
+ *
+ * Thanks to David Keppel that explained me this "simple" trick.
+ *
+ *
+ * 3) C languace code debugging
+ * This software was developed and debugged using the Metrowerks
+ * Code Warrior PPC integrated assembler. It can be still used with the
+ * Code Warrior compiler by means of the file "powerpc_mach_asm_debug.c"
+ * that include it.
+ * In order to avoid "copy and paste" bugs, and make easyer the maintaining,
+ * I made the minimal changes, so you can find some strange code as:
+ *
+ * #if 0
+ * .if 0
+ * C code here
+ * .endif
+ * #endif
+ *
+ * This is just to embed some C code that is needed by the Code Warrior
+ * integrated assembler.
+ *
+ *
+ * 4) Assembly constants generation
+ * Constants used in the assembly code are generated by running
+ * the C code in the sequel (commented). It uses the C macros declared in
+ * the C heather in order to guarantee that the C interface and the assebly
+ * code are "aligned". I avoided the use of an assebler preprocessor since
+ * they are not so standard and moreover using macro espressions makes the
+ * assembly debugging more difficult.
+ *
+ *
+
+
+#include <iostream>
+#include "powerpc_mach.h"
+
+int main()
+{
+ using namespace std;
+
+ int i;
+
+ cout << ".set LR_SAVE, " << PPC_LR_SAVE << endl;
+ cout << ".set CR_SAVE, " << PPC_CR_SAVE << endl;
+ cout << ".set BLOCKI_FSIZE, " << QUICKTHREADS_BLOCKI_FRAME_SIZE << endl;
+ cout << ".set BLOCK_FSIZE, " << QUICKTHREADS_BLOCK_FRAME_SIZE << endl;
+
+ cout << endl;
+ for(i=0; i<12; i++)
+ cout << ".set PAR_" << i << ", " << PPC_PAR(i) << endl;
+
+ cout << endl;
+ i = 13;
+ cout << ".set GPR_SAVE_" << i << ", " << QUICKTHREADS_BLOCKI_GPR_SAVE(i) << endl;
+
+ cout << endl;
+ for(i=31; i>13; i--)
+ cout << ".set FPR_SAVE_" << i << ", " << QUICKTHREADS_BLOCK_FPR_SAVE(i) << endl;
+
+ cout << endl;
+ cout << ".set VARGS_BKOFF, " << QUICKTHREADS_VARGS_BKOFF << endl;
+
+
+ cout << endl << endl << endl;
+
+ for(i=31; i>13; i--)
+ cout << "\tstfd\tf" << i << ",FPR_SAVE_" << i << "(r1)" << endl;
+
+ cout << endl;
+ for(i=31; i>13; i--)
+ cout << "\tlfd \tf" << i << ",FPR_SAVE_" << i << "(r1)" << endl;
+
+ cout << endl << endl << endl;
+
+
+ return 0;
+}
+
+
+ *
+ *
+ *
+ */
+
+
+#if 0
+
+ .text
+ .align 4
+
+ .globl qt_block
+ .globl _qt_block
+ .globl qt_blocki
+ .globl _qt_blocki
+ .globl qt_abort
+ .globl _qt_abort
+ .globl qt_start
+ .globl _qt_start
+ .globl qt_vstart
+ .globl _qt_vstart
+
+
+.set LR_SAVE, 8
+.set CR_SAVE, 4
+.set BLOCKI_FSIZE, 128
+.set BLOCK_FSIZE, 192
+
+.set PAR_0, 24
+.set PAR_1, 28
+.set PAR_2, 32
+.set PAR_3, 36
+.set PAR_4, 40
+.set PAR_5, 44
+.set PAR_6, 48
+.set PAR_7, 52
+.set PAR_8, 56
+.set PAR_9, 60
+.set PAR_10, 64
+.set PAR_11, 68
+
+.set GPR_SAVE_13, 52
+
+.set FPR_SAVE_31, 184
+.set FPR_SAVE_30, 176
+.set FPR_SAVE_29, 168
+.set FPR_SAVE_28, 160
+.set FPR_SAVE_27, 152
+.set FPR_SAVE_26, 144
+.set FPR_SAVE_25, 136
+.set FPR_SAVE_24, 128
+.set FPR_SAVE_23, 120
+.set FPR_SAVE_22, 112
+.set FPR_SAVE_21, 104
+.set FPR_SAVE_20, 96
+.set FPR_SAVE_19, 88
+.set FPR_SAVE_18, 80
+.set FPR_SAVE_17, 72
+.set FPR_SAVE_16, 64
+.set FPR_SAVE_15, 56
+.set FPR_SAVE_14, 48
+
+
+/* various offsets used by "qt_varg" */
+.set P_T, PAR_0
+.set P_STARTUP, PAR_1
+.set P_USERF, PAR_2
+.set P_CLEANUP, PAR_3
+ /* the offset used to move back the linkage area to be adiacent to
+ * the variant argument list before calling "userf(...) */
+.set VARGS_BKOFF, 16 /* skip "t", "startup", "userf" and "cleanup" */
+
+ /* location where "t" and "cleanup" are saved (with respect of
+ * the stack frame base) */
+.set P_T_SAVE, -4
+.set P_CLEANUP_SAVE, -8
+
+#endif
+
+
+
+/* Block the current thread saving all integer non volatile registers and
+ * start a new thread.
+ */
+#if 0
+.if 0
+#endif
+void *qt_blocki (void *helper, void *a0, void *a1, void *newthread);
+asm void *qt_blocki (void *helper, void *a0, void *a1, void *newthread)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+qt_blocki:
+_qt_blocki:
+#endif
+/* prolog code */
+ stwu r1,-BLOCKI_FSIZE(r1) /* allocate the stack frame */
+ mflr r0 /* return addr in r0 */
+ mfcr r11 /* CR in r11 */
+ stw r0,LR_SAVE+BLOCKI_FSIZE(r1) /* save return addr in the stack */
+ stw r11,CR_SAVE+BLOCKI_FSIZE(r1) /* save CR in the stack */
+ stmw r13,GPR_SAVE_13(r1) /* save non-volatile reg */
+
+/* call helper(qt_t *old, void *a0, void *a1) */
+ mtlr r3 /* "helper" addr in the link reg */
+ mr r3,r1 /* current thread (i.e. the SP) in arg "old" */
+ mr r1,r6 /* swap to the new thread (i.e. to its SP) */
+ blrl /* jump to "helper" */
+/* the "helper" return value is returned (since r3 is not changed) */
+
+/* epilog code: return to the new thread's "qt_blocki" caller */
+ lmw r13,GPR_SAVE_13(r1) /* restore non-volatile reg */
+ lwz r0,LR_SAVE+BLOCKI_FSIZE(r1) /* recover return addr */
+ lwz r11,CR_SAVE+BLOCKI_FSIZE(r1) /* recover CR */
+ mtlr r0 /* return address in the link reg */
+ mtcr r11 /* restore CR */
+ addi r1,r1,BLOCKI_FSIZE /* free the stack frame */
+ blr /* return */
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+/* Abort the current thread and start a new thread.
+ */
+#if 0
+.if 0
+#endif
+void qt_abort (void *helper, void *a0, void *a1, void *newthread);
+asm void qt_abort (void *helper, void *a0, void *a1, void *newthread)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+qt_abort:
+_qt_abort:
+#endif
+/* prolog code */
+/* there is no prolog. It will never come back */
+
+/* call helper(qt_t *old, void *a0, void *a1) */
+ mtlr r3 /* "helper" addr in the link reg */
+ mr r1,r6 /* swap to the new thread (i.e. to its SP) */
+/* we don't need to set "old", we can pass just garbage. Actually, since r3
+ is not changed, "old" is set to "helper" (don't care) */
+ blrl /* call "helper" */
+/* the "helper" return value is returned (since r3 is not changed) */
+
+/* epilog code: return to the new thread's "qt_blocki" caller */
+ lmw r13,GPR_SAVE_13(r1) /* restore non-volatile reg */
+ lwz r0,LR_SAVE+BLOCKI_FSIZE(r1) /* recover return addr */
+ lwz r11,CR_SAVE+BLOCKI_FSIZE(r1) /* recover CR */
+ mtlr r0 /* return address in the link reg */
+ mtcr r11 /* restore CR */
+ addi r1,r1,BLOCKI_FSIZE /* free the stack frame */
+ blr /* return */
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+/* Block the current thread saving all non volatile registers and start
+ * a new thread.
+ */
+#if 0
+.if 0
+#endif
+void *qt_block (void *helper, void *a0, void *a1, void *newthread);
+asm void *qt_block (void *helper, void *a0, void *a1, void *newthread)
+{
+#if 0
+.endif
+#endif
+
+# if 0
+qt_block:
+_qt_block:
+#endif
+/* prolog code */
+ stwu r1,-BLOCK_FSIZE(r1) /* allocate the stack frame */
+ mflr r0 /* return addr in r0 */
+ stw r0,LR_SAVE+BLOCK_FSIZE(r1) /* save return addr in the stack */
+
+/* save non-volatile fp reg */
+ stfd f31,FPR_SAVE_31(r1)
+ stfd f30,FPR_SAVE_30(r1)
+ stfd f29,FPR_SAVE_29(r1)
+ stfd f28,FPR_SAVE_28(r1)
+ stfd f27,FPR_SAVE_27(r1)
+ stfd f26,FPR_SAVE_26(r1)
+ stfd f25,FPR_SAVE_25(r1)
+ stfd f24,FPR_SAVE_24(r1)
+ stfd f23,FPR_SAVE_23(r1)
+ stfd f22,FPR_SAVE_22(r1)
+ stfd f21,FPR_SAVE_21(r1)
+ stfd f20,FPR_SAVE_20(r1)
+ stfd f19,FPR_SAVE_19(r1)
+ stfd f18,FPR_SAVE_18(r1)
+ stfd f17,FPR_SAVE_17(r1)
+ stfd f16,FPR_SAVE_16(r1)
+ stfd f15,FPR_SAVE_15(r1)
+ stfd f14,FPR_SAVE_14(r1)
+/* block the thread */
+ bl qt_blocki
+/* the thread is going to be resumed */
+/* restore non-volatile fp reg */
+ lfd f31,FPR_SAVE_31(r1)
+ lfd f30,FPR_SAVE_30(r1)
+ lfd f29,FPR_SAVE_29(r1)
+ lfd f28,FPR_SAVE_28(r1)
+ lfd f27,FPR_SAVE_27(r1)
+ lfd f26,FPR_SAVE_26(r1)
+ lfd f25,FPR_SAVE_25(r1)
+ lfd f24,FPR_SAVE_24(r1)
+ lfd f23,FPR_SAVE_23(r1)
+ lfd f22,FPR_SAVE_22(r1)
+ lfd f21,FPR_SAVE_21(r1)
+ lfd f20,FPR_SAVE_20(r1)
+ lfd f19,FPR_SAVE_19(r1)
+ lfd f18,FPR_SAVE_18(r1)
+ lfd f17,FPR_SAVE_17(r1)
+ lfd f16,FPR_SAVE_16(r1)
+ lfd f15,FPR_SAVE_15(r1)
+ lfd f14,FPR_SAVE_14(r1)
+
+ lwz r0,LR_SAVE+BLOCK_FSIZE(r1) /* recover return addr */
+ mtlr r0 /* return address in the link reg */
+ addi r1,r1,BLOCK_FSIZE /* free the stack frame */
+ blr /* return */
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+/* Start a single argument thread using parameters preloaded in the stack
+ * during thread initialization (see comments on stack initialization in the
+ * heather file).
+ *
+ * Executes:
+ *
+ * only(u, t, userf);
+ */
+#if 0
+.if 0
+#endif
+void qt_start(void);
+asm void qt_start(void)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+qt_start:
+_qt_start:
+#endif
+ lwz r3,PAR_0(r1) /* "u" in r3 */
+ lwz r4,PAR_1(r1) /* "t" in r4 */
+ lwz r5,PAR_2(r1) /* "userf" in r5 */
+ lwz r6,PAR_3(r1) /* "only" in r6 */
+ mtlr r6 /* "only" address in the link reg */
+/* call only(u, t, userf) */
+ blrl /* jump to "only" */
+/* error if it returns */
+ b _qt_error
+/* dead code (some inline asm "wants" the epilog, or they genetare it) */
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+/* Start a variant argument thread using parameters preloaded in the stack
+ * during thread initialization (see comments on stack initialization in the
+ * heather file).
+ *
+ * Executes:
+ *
+ * startup(t);
+ * userf_return = userf(...);
+ * cleanup(pt, userf_return);
+ *
+
+
+ ***** Stack layout on start *****
+
+
+ backchain -> STACK BOTTOM (higher address)
+ +==========================+
+ backchain - 4 -> | |
+ + LOCAL VARIABLES AREA +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ | | arg(n)
+ + +
+ | |
+ + VARIABLE ARGUMENT LIST +
+ ..............
+ + for userf call +
+ SP + PAR(5) -> | | arg(1)
+ + +
+ SP + PAR(4) -> | | arg(0)
+ +--------------------------+
+ SP + PAR(3) -> | | cleanup par
+ + +
+ SP + PAR(2) -> | | userf par
+ + PARAMETER AREA +
+ SP + PAR(1) -> | | startup par
+ + +
+ SP + PAR(0) -> | | t par
+ +--------------------------+
+ | |
+ + LINKAGE AREA +
+ SP -> | |
+ +==========================+
+ STACK TOP (lower address)
+
+ Stack grows down
+ |
+ V
+
+
+
+ ***** Stack layout before call userf *****
+
+
+ backchain -> STACK BOTTOM (higher address)
+ +==========================+
+ backchain - 4 -> | |
+ + LOCAL VARIABLES AREA +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ | | arg(n)
+ + +
+ | |
+ + VARIABLE ARGUMENT LIST +
+ ..............
+ + for userf call +
+ SP + PAR(1) -> | | arg(1)
+ + +
+ SP + PAR(0) -> | | arg(0)
+ +--------------------------+
+ | |
+ + LINKAGE AREA +
+ SP -> | |
+ +==========================+
+ STACK TOP (lower address)
+
+ Stack grows down
+ |
+ V
+
+
+ * To call "userf(...)", the argument list must be adiacent to the linkage
+ * area. Instead of copy the argument list, we move back the linkage area
+ * (actually, we just increase the SP and copy the backchain). "t" and
+ * "cleanup" are saved in a local variable area in order to call
+ * cleanup(pt, userf_return).
+
+*/
+
+
+#if 0
+.if 0
+#endif
+void qt_vstart(void);
+asm void qt_vstart(void)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+qt_vstart:
+_qt_vstart:
+#endif
+/* NOTICE: the callee routines could save parameter registers in the caller's
+ * stack parameter area. We put "t" in PAR(0) in such a way, if startup(t)
+ * will save "t", it will be saved on the same location thus not delething
+ * any other parameter.
+ */
+
+/* since we will move back the linckage area (to make it adiacent to the
+ * parameter list), we need to save "t" and "cleanup". We have made room for
+ * this on the bottom of the stack frame. */
+
+/* save parameters in the local variable area */
+ lwz r11,0(r1) /* get the backchain */
+ lwz r3,P_T(r1)
+ lwz r4,P_CLEANUP(r1)
+ stw r3,P_T_SAVE(r11) /* save "pt" */
+ stw r4,P_CLEANUP_SAVE(r11) /* save "cleanup" */
+
+/* call startup(t) */
+ lwz r5,P_STARTUP(r1)
+ mtlr r5
+ blrl /* call "startup" */
+
+/* call userf(...) */
+ lwz r11,0(r1) /* reload backchain (r11 is volatile) */
+ lwz r4,P_USERF(r1) /* load "userf" */
+ mtlr r4
+
+ /* first eight parameter of the variant list must be copyed in
+ * GPR3-GPR10. There is a four places offset due to "t", "startup",
+ * userf" and "cleanup" */
+
+ lwz r3,PAR_4(r1)
+ lwz r4,PAR_5(r1)
+ lwz r5,PAR_6(r1)
+ lwz r6,PAR_7(r1)
+ lwz r7,PAR_8(r1)
+ lwz r8,PAR_9(r1)
+ lwz r9,PAR_10(r1)
+ lwz r10,PAR_11(r1)
+
+
+ /* move the linkage area to be adiacent to the argument list */
+ stw r11,VARGS_BKOFF(r1) /* copy backchain */
+ addi r1,r1,VARGS_BKOFF /* move back the stack */
+
+ blrl /* call "userf" */
+
+/* call qt_cleanup(void *pt, void *vuserf_return) */
+ lwz r11,0(r1) /* reload backchain (r11 is volatile) */
+
+ mr r4,r3 /* push "userf" return as 2nd parameter */
+ lwz r3,P_T_SAVE(r11) /* reload "pt" */
+ lwz r5,P_CLEANUP_SAVE(r11) /* reload "cleanup" */
+ mtlr r5
+ blrl
+ b _qt_error
+/* dead code (some inline asm "wanst" the epilog, or they genetare it) */
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
diff --git a/ext/systemc/src/sysc/qt/md/powerpc_mach_b.s b/ext/systemc/src/sysc/qt/md/powerpc_mach_b.s
new file mode 100644
index 000000000..f0fd23fcb
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/powerpc_mach_b.s
@@ -0,0 +1,290 @@
+/* speed test for basic CPU operations */
+
+
+/* Marco Bucci <marco.bucci@inwind.it> */
+
+/* This code was developed with the Code Warrior integrate ppc assembler.
+ * Macros are use to hide illegal constructs whether you are using a
+ * "normal" assembler or the "C integrated" assembler.
+ */
+
+#if 0
+
+
+ .text
+ .align 4
+
+ .globl b_call_reg
+ .globl _b_call_reg
+ .globl b_call_imm
+ .globl _b_call_imm
+ .globl b_add
+ .globl _b_add
+ .globl b_load
+ .globl _b_load
+
+.set fsize, 64
+.set lrsave, 8
+
+#else
+
+#define fsize 64
+#define lrsave 8
+
+#endif
+
+
+
+
+#if 0
+.if 0
+#endif
+asm void b_null(void)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+b_null:
+#endif
+
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+/* actually the same as the following. How to get "b_null" address?
+ * I didnt find the right sintax or the right way.
+ * I should take the current PC, then the difference to "b_null"
+ * (making the difference beween the labels), perform the sum and go?!
+ */
+#if 0
+.if 0
+#endif
+asm void b_call_reg(long n)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+b_call_reg:
+_b_call_reg:
+#endif
+
+ mflr r0
+ stw r31,-4(r1)
+ stw r30,-8(r1)
+ stw r0,lrsave(r1)
+ stwu r1,-fsize(r1)
+ mr r30,r3
+ li r31,0
+
+ b L1
+L0:
+ bl b_null
+ bl b_null
+ bl b_null
+ bl b_null
+ bl b_null
+
+ addi r31,r31,5
+L1:
+ cmpw r31,r30
+ blt L0
+
+
+ lwz r0,lrsave+fsize(r1)
+ mtlr r0
+ lwz r31,-4+fsize(r1)
+ lwz r30,-8+fsize(r1)
+ addi r1,r1,fsize
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+
+#if 0
+.if 0
+#endif
+asm void b_call_imm(long n)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+b_call_imm:
+_b_call_imm:
+#endif
+
+ mflr r0
+ stw r31,-4(r1)
+ stw r30,-8(r1)
+ stw r0,lrsave(r1)
+ stwu r1,-fsize(r1)
+ mr r30,r3
+ li r31,0
+
+ b L3
+L2:
+ bl b_null
+ bl b_null
+ bl b_null
+ bl b_null
+ bl b_null
+
+ addi r31,r31,5
+L3:
+ cmpw r31,r30
+ blt L2
+
+
+ lwz r0,lrsave+fsize(r1)
+ mtlr r0
+ lwz r31,-4+fsize(r1)
+ lwz r30,-8+fsize(r1)
+ addi r1,r1,fsize
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+#if 0
+.if 0
+#endif
+asm void b_add(long n)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+b_add:
+_b_add:
+#endif
+
+ mflr r0
+ stw r31,-4(r1)
+ stw r30,-8(r1)
+ stw r0,lrsave(r1)
+ stwu r1,-fsize(r1)
+ mr r30,r3
+ li r31,0
+
+ b L5
+L4:
+ addi r3,r3,5
+ addi r4,r4,5
+ addi r5,r5,5
+ addi r6,r6,5
+ addi r7,r7,5
+
+ addi r3,r3,5
+ addi r4,r4,5
+ addi r5,r5,5
+ addi r6,r6,5
+ addi r7,r7,5
+
+ addi r31,r31,10
+L5:
+ cmpw r31,r30
+ blt L4
+
+
+ lwz r0,lrsave+fsize(r1)
+ mtlr r0
+ lwz r31,-4+fsize(r1)
+ lwz r30,-8+fsize(r1)
+ addi r1,r1,fsize
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+#if 0
+.if 0
+#endif
+asm void b_load(long n)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+b_load:
+_b_load:
+#endif
+
+ mflr r0
+ stw r31,-4(r1)
+ stw r30,-8(r1)
+ stw r0,lrsave(r1)
+ stwu r1,-fsize(r1)
+ mr r30,r3
+ li r31,0
+
+ b L7
+L6:
+ lwz r3,4(r1)
+ lwz r4,8(r1)
+ lwz r5,12(r1)
+ lwz r6,16(r1)
+ lwz r7,20(r1)
+
+ lwz r3,24(r1)
+ lwz r4,28(r1)
+ lwz r5,32(r1)
+ lwz r6,36(r1)
+ lwz r7,40(r1)
+
+
+ addi r31,r31,10
+L7:
+ cmpw r31,r30
+ blt L6
+
+
+ lwz r0,lrsave+fsize(r1)
+ mtlr r0
+ lwz r31,-4+fsize(r1)
+ lwz r30,-8+fsize(r1)
+ addi r1,r1,fsize
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
diff --git a/ext/systemc/src/sysc/qt/md/powerpc_sys5.h b/ext/systemc/src/sysc/qt/md/powerpc_sys5.h
new file mode 100644
index 000000000..8c0730704
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/powerpc_sys5.h
@@ -0,0 +1,566 @@
+/*
+ + * QuickThreads -- Threads-building toolkit.
+ + * Copyright (c) 1993 by David Keppel
+ + *
+ + * Permission to use, copy, modify and distribute this software and
+ + * its documentation for any purpose and without fee is hereby
+ + * granted, provided that the above copyright notice and this notice
+ + * appear in all copies. This software is provided as a
+ + * proof-of-concept and for demonstration purposes; there is no
+ + * representation about the suitability of this software for any
+ + * purpose.
+ + *
+
+ + * PowerPC-Sys5 thread switching module.
+ + *
+ + * This software is largely based on the original PowerPC-Linux porting
+ + * developed by Ken Aaker <kenaaker@silverbacksystems.com>
+ + *
+ + * Marco Bucci <marco.bucci@inwind.it>
+ + * December 2002
+ + *
+ + */
+
+
+#ifndef QUICKTHREADS_POWERPC_H
+#define QUICKTHREADS_POWERPC_H
+
+
+/*****************************************************************************
+ *
+ * DESCRIPTION
+ *
+ * This is the QuickThreads switching module implementation for PowerPC
+ * running under System V ABI (Application Binary Interface) [2]. It was
+ * developed by porting the MacOS X version and tested under LinuxPPC.
+ *
+ * Notice that this is not the same than the PowerPC Mach ABI used by MacOSX
+ * [1].
+ *
+ * IMPLEMENTATION NOTES
+ *
+ * 1) Porting on System V ABI
+ * Excluding the variant argument calling convention, Mach and System V ABI
+ * are enough similar and it could be possible to use some simple macro, to
+ * adapt the code for both the ABIs. Actually, the only relevant difference
+ * is in the linkage area structure and in the position where the Link and
+ * the Condition registers are saved. As to the calling conventions, there
+ * are differences with floating points argument passing and with variant
+ * argument lists. Notice that, on Mach, the caller's stack frame allocates
+ * space to hold all arguments ([1] p.51), while on System V, the caller's
+ * stack frame allocates space to hold just the arguments that don't fit into
+ * registers ([2] p.3.18).
+ *
+ * 2) Variant argument list implementation
+ * Variant argument calling on a RISC machine is not easy to implement since
+ * parameters are passed via registers instead of via stack. In a general
+ * variant argument implementation, the caller's stack must map the whole
+ * parameter list following the rules related to the use of the GPR and FPR
+ * parameter registers and the stack alignment ([2] p.3-21).
+ * This implementation is quite simple and not general. It works under the
+ * hypothesis that arguments are 4-bytes aligned integers.
+ *
+ * 3) This heather file organisation
+ * I preferred to not make confusion between macros that are needed (i.e.
+ * directly used) by QuickThreads and internal "implementation" macros. You
+ * will find QuickThreds macros in the end of this header. Sometime they just
+ * refer to an analogous "internal" macro. On the top, there are the macros
+ * that I used to make more clean (I hope) the implementation. I could include
+ * some system heather (as to stack layout definitions, prologs and epilogs,
+ * etc.), but I preferred to have a self-contained heather in order to make
+ * all more clear for mantaining and for possible porting on another ABI.
+ *
+ *
+ * REFERENCES
+ *
+ * [1] - Mach-O Runtime Architecture
+ * Runtime Concepts and Conventions for Mac OS X Programs
+ * Preliminary July 2002
+ *
+ * [2] - SYSTEM V APPLICATION BINARY INTERFACE
+ * PowerPC Processor Supplement
+ * September 1995
+ *
+
+ *****************************************************************************/
+
+/*****************************************************************************
+ *
+ * PowerPC System V Stack frame (see [2])
+ *
+
+ ................
+ + +
+ | |
+ +--------------------------+
+ | | Caller's LR
+ + CALLER'S LINKAGE AREA +
+ backchain -> | | Caller's backchain
+ +==========================+
+ | | FPR31
+ + FPR SAVE AREA +
+ ..............
+ + +
+ | | FPRn
+ +--------------------------+
+ | | GPR31
+ + GPR SAVE AREA +
+ ..............
+ + +
+ | | GPRn
+ +--------------------------+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ | CR SAVE |
+ +--------------------------+
+ | |
+ + LOCAL VARIABLES AREA +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ | | PAR(n-7)
+ + +
+ | |
+ + PARAMETER AREA +
+ ..............
+ + for FUTURE call +
+ | | PAR(9)
+ + +
+ SP + 8 -> | | PAR(8)
+ +--------------------------+
+ SP + 4 -> | | LR callee-save for FUTURE call
+ + LINKAGE AREA +
+ SP -> | | backchain
+ +==========================+
+ STACK TOP (lower address)
+
+ Stack grows down
+ |
+ V
+
+
+ * NOTE:
+ *
+ * 1) In this figure parameter are supposed to be integer 4-bytes aligned and
+ * are numbered 0, 1, 2,... n.
+ *
+ * 2) Parameter are allocated in the CALLER's parameter area. This area must
+ * be large enough to hold all parameters that cannot fit in registers (no
+ * more parameter registers are available);
+ *
+ * 3) The callee saves LR in the caller's linkage area. CR as all other
+ * callee's state are saved in its own stack frame.
+ *
+
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *
+ * Stack initialization for a single argument thread
+ *
+
+
+ top + QUICKTHREADS_STKBASE -> STACK BOTTOM (higher address)
+ +==========================+
+ | |
+ + +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ top + QUICKTHREADS_ONLY_INDEX * 4 -> | only param | PAR(3)
+ + +
+ top + QUICKTHREADS_USER_INDEX * 4 -> | userf param | PAR(2)
+ + +
+ top + QUICKTHREADS_ARGT_INDEX * 4 -> | t param | PAR(1)
+ + +
+ top + QUICKTHREADS_ARGU_INDEX * 4 -> | u param | PAR(0)
+ +--------------------------+
+ top + QUICKTHREADS_RETURN_INDEX * 4 -> | qt_start | LR save
+ + +
+ top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE | backchain
+ +==========================+
+ | |
+ + +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ | |
+ + +
+ top -> |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain
+ +==========================+
+ STACK TOP (lower address)
+
+ Stack grows down
+ |
+ V
+
+ *****************************************************************************
+ *
+ * Stack initialization for a variant argument thread
+ *
+
+ bottom -> STACK BOTTOM (higher address)
+ +==========================+
+ | |
+ + +
+ ..............
+ + +
+ top + QUICKTHREADS_VSTKBASE -> | arg(0) | PAR(4)
+ +--------------------------+
+ top + QUICKTHREADS_CLEANUP_INDEX * 4 -> | cleanup param | PAR(3)
+ + +
+ top + QUICKTHREADS_USER_INDEX * 4 -> | userf param | PAR(2)
+ + +
+ top + QUICKTHREADS_VSTARTUP_INDEX * 4 ->| startup param | PAR(1)
+ + +
+ top + QUICKTHREADS_ARGT_INDEX * 4 -> | t param | PAR(0)
+ +--------------------------+
+ top + QUICKTHREADS_RETURN_INDEX * 4 -> | qt_start | LR save
+ + +
+ top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE | backchain
+ +==========================+
+ | |
+ + +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ | |
+ + +
+ top -> |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain
+ +==========================+
+ STACK TOP (lower address)
+
+ Stack grows down
+ |
+ V
+
+* NOTE:
+*
+* Parameters are passed to "qt_start" or to "qt_vstart" putting them into
+* the stack frames of "qt_start" or "qt_vstart" themselves. This not a
+* conventional parameter passing because parameters should be put into the
+* caller's stack, not into the callee's one. Actually we must consider
+* that as a preload of the parameter area that "qt_start" or "qt_vstart"
+* will use for their own calls.
+* Be aware of the fact that, during a call, the caller's parameter area is,
+* in a certain sense, volatile. In facts, the callee can save parameter
+* registers on the caller's parameter area.
+*
+ *****************************************************************************/
+
+
+/*****************************************************************************
+
+ Define PowerPC System V related macros
+
+ *****************************************************************************/
+
+
+
+typedef unsigned long PPC_W;
+
+/* Stack pointer must always be a multiple of 16 */
+#define PPC_STACK_INCR 16
+#define PPC_ROUND_STACK(length) \
+ (((length)+PPC_STACK_INCR-1) & ~(PPC_STACK_INCR-1))
+
+
+#define PPC_LINKAGE_AREA 8
+#define PPC_LR_SAVE 4
+
+#define PPC_PARAM_AREA(n) (4*(n))
+
+#define PPC_GPR_SAVE_AREA (4*19) /* GPR13-GPR31 must be saved */
+#define PPC_FPR_SAVE_AREA (8*18) /* FPR14-FPR31 must be saved */
+
+/* Define parameter offset on the stack.
+ * NOTICE: Parameters are numbered 0, 1, ..., n.
+*/
+#define PPC_PAR(i) (PPC_LINKAGE_AREA+(i)*4)
+
+/*****************************************************************************
+
+ Define stack frames
+
+ *****************************************************************************/
+
+
+/* Define the "qt_blocki" and "qt_abort" stack frame. We use the same stack
+ * frame for both.
+ *
+
+ top + S ->
+ +==========================+
+ top + S - 4 -> | | GPR31
+ + GPR SAVE AREA +
+ ..............
+ + +
+ top + S - 19 * 4 -> | | GPR13
+ +--------------------------+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ top + 8 -> | CR SAVE |
+ +--------------------------+
+ | |
+ + LINKAGE AREA +
+ top -> | |
+ +==========================+
+ */
+
+#define QUICKTHREADS_BLOCKI_FRAME_SIZE \
+ PPC_ROUND_STACK(PPC_LINKAGE_AREA+4+PPC_GPR_SAVE_AREA)
+
+#define QUICKTHREADS_BLOCKI_CR_SAVE 8
+
+/* Offset to the base of the GPR save area. Save from GPR13 to GPR31
+ * increasing address.
+ */
+#define QUICKTHREADS_BLOCKI_GPR_SAVE(i) (QUICKTHREADS_BLOCKI_FRAME_SIZE-4+(i-31)*4)
+
+
+
+/* Define the "qt_block" stack frame. Notice that since "qt_black" calls
+ * "qt_blocki", GPR registers are saved into "qt_blocki" stack frame.
+ *
+
+ top + S ->
+ +==========================+
+ top + S - 8 -> | | FPR31
+ + FPR SAVE AREA +
+ ..............
+ + +
+ top + S - 18 * 8 -> | | FPR14
+ +--------------------------+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ | |
+ + LINKAGE AREA +
+ top -> | |
+ +==========================+
+ */
+
+#define QUICKTHREADS_BLOCK_FRAME_SIZE \
+ PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_FPR_SAVE_AREA)
+
+/* Offset to the location where registers are saved.
+ */
+#define QUICKTHREADS_BLOCK_FPR_SAVE(i) (QUICKTHREADS_BLOCK_FRAME_SIZE-8+(i-31)*8)
+
+
+/* Define the "qt_start" frame size. It consists just of the linkage area and
+ * the parameter area.
+ *
+
+ +==========================+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ | | only par
+ + +
+ | | userf par
+ + PARAMETER AREA +
+ | | t par
+ + +
+ top + 8 -> | | u par
+ +--------------------------+
+ | |
+ + LINKAGE AREA +
+ top -> | |
+ +==========================+
+
+ */
+#define QUICKTHREADS_START_FRAME_SIZE PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4))
+
+
+
+/* Define the "qt_vstart" frame. It consists of the linkage area, the fix parameter
+ * area, the variant argument list and a local variable area used in "qt_vstart"
+ * implementation.
+ *
+
+ backchain ->
+ +==========================+
+ backchain - 4 -> | |
+ + LOCAL VARIABLES AREA +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ | | arg(n)
+ + +
+ | |
+ + VARIABLE ARGUMENT LIST +
+ ..............
+ + for userf call +
+ | | arg(1)
+ + +
+ top + 8 + 16 -> | | arg(0)
+ +--------------------------+
+ | | cleanup par
+ + +
+ | | userf par
+ + PARAMETER AREA +
+ | | startup par
+ + +
+ top + 8 -> | | t par
+ +--------------------------+
+ | |
+ + LINKAGE AREA +
+ top -> | |
+ +==========================+
+
+ */
+#define QUICKTHREADS_VARGS_LOCAL_AREA (4*4) /* local variable area */
+
+/* The offset the stack will be moved back before to call "userf(...)".
+ * The linckage area must be moved to be adiacent to the part of the variant
+ * argument list that is in the stack. Notice that, since the first 8
+ * parameters are passed via registers, the offset is equal to the size of
+ * 4+8 parameters. */
+#define QUICKTHREADS_VARGS_BKOFF PPC_PARAM_AREA(4+8)
+
+#define QUICKTHREADS_VSTART_FRAME_SIZE(varbytes) \
+ PPC_ROUND_STACK(PPC_LINKAGE_AREA+QUICKTHREADS_VARGS_BKOFF+(varbytes)+ \
+ QUICKTHREADS_VARGS_LOCAL_AREA)
+
+/* Offset to the base of the varian argument list */
+#define QUICKTHREADS_VSTART_LIST_BASE (PPC_LINKAGE_AREA+PPC_PARAM_AREA(4))
+
+
+/* Notice that qt_start and qt_vstart have no parameters, actually their
+ * parameters are written in their stack frame during thread initialization
+ */
+extern void qt_start(void);
+extern void qt_vstart(void);
+
+
+
+/* Offset (in words) of the location where the block routine saves its return
+ * address (i.e. LR). SP points the top of the block routine stack and,
+ * following ppc calling conventions, the return address is saved in the
+ * previous (caller's) stack frame.
+ */
+#define QUICKTHREADS_RETURN_INDEX ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_LR_SAVE)/sizeof(PPC_W))
+
+/* static variable used to get the stack bottom in "VARGS" initialization */
+static void *qt_sp_bottom_save;
+
+#define QUICKTHREADS_ARG_INDEX(i) ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_PAR(i))/sizeof(PPC_W))
+
+/*****************************************************************************
+
+ QuickThreads needed definitions
+
+ *****************************************************************************/
+
+
+#define QUICKTHREADS_GROW_DOWN
+#define QUICKTHREADS_STKALIGN PPC_STACK_INCR
+typedef PPC_W qt_word_t;
+
+
+/* This macro is used by "QUICKTHREADS_ARGS" to initialize a single argument thread.
+ * - set "qt_start" as the "qt_block" or "qt_blocki" return address;
+ * - set the top of the stack backchain;
+ * - set the next backchain (not needed, but just to be "clean").
+ */
+#define QUICKTHREADS_ARGS_MD(sp) \
+ (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_start), \
+ QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \
+ QUICKTHREADS_SPUT (sp, QUICKTHREADS_BLOCKI_FRAME_SIZE/sizeof(PPC_W), \
+ sp+QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE))
+
+
+/* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread.
+ * It returns the pointer to the top of the argument list.
+ * We also use it to get the stack bottom via a static variable. This is a bit
+ * "dirty", it could be better to do it in "qt_vargs", but we don't want change
+ * anything out of this file.
+ * We need the stack bottom to allocate a local variable area used by
+ * "qt_vstart".
+ */
+#define QUICKTHREADS_VARGS_MD0(sp, varbytes) \
+ ((qt_sp_bottom_save = sp), \
+ ((qt_t *)(((char *)(sp)) - \
+ (QUICKTHREADS_VSTART_FRAME_SIZE(varbytes)-QUICKTHREADS_VSTART_LIST_BASE))))
+
+
+/* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread.
+ * - set "qt_start" as the "qt_block" or "qt_blocki" return address;
+ * - set the top of the stackback chain;
+ * - set the next backchain (it points the stack botton).
+ */
+#define QUICKTHREADS_VARGS_MD1(sp) \
+ (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_vstart), \
+ QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \
+ QUICKTHREADS_SPUT (sp, (QUICKTHREADS_BLOCKI_FRAME_SIZE)/sizeof(PPC_W), \
+ qt_sp_bottom_save))
+
+
+/* Activate "qt_vargs" as the initialization routine for the variant
+ * argument threads
+ */
+#define QUICKTHREADS_VARGS_DEFAULT
+
+/* Override "qt_vargs" with "qt_vargs_stdarg".
+ * On LinuxPPC "qt_vargs" doesn't work, "qt_vargs_stdarg" uses a more
+ * standard way to retrieve arguments from the variant list.
+ */
+#define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \
+ ((qt_t *)qt_vargs_stdarg (sp, nbytes, vargs, pt, startup, vuserf, cleanup))
+
+
+/* This macro is used by "QUICKTHREADS_ADJ(sp)" to get the stack top form the stack
+ * bottom during a single argument thread initialization.
+ * It is the space we need to allocate for a single argument thread: the stack
+ * frame for the block routine ("qt_block" or "qt_blocki") and for "qt_start".
+ */
+#define QUICKTHREADS_STKBASE \
+ (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE)
+
+/* This macro is used by "QUICKTHREADS_VADJ(sp)" to get the stack top from the base
+ * of the variant argument list during a variant argument thread initialization.
+ */
+#define QUICKTHREADS_VSTKBASE (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_VSTART_LIST_BASE)
+
+/* The *index* (positive offset) of where to put each value. */
+
+#define QUICKTHREADS_ARGU_INDEX QUICKTHREADS_ARG_INDEX(0)
+#define QUICKTHREADS_ARGT_INDEX QUICKTHREADS_ARG_INDEX(1)
+#define QUICKTHREADS_USER_INDEX QUICKTHREADS_ARG_INDEX(2)
+#define QUICKTHREADS_ONLY_INDEX QUICKTHREADS_ARG_INDEX(3)
+
+
+#define QUICKTHREADS_VARGT_INDEX QUICKTHREADS_ARG_INDEX(0)
+#define QUICKTHREADS_VSTARTUP_INDEX QUICKTHREADS_ARG_INDEX(1)
+#define QUICKTHREADS_VUSERF_INDEX QUICKTHREADS_ARG_INDEX(2)
+#define QUICKTHREADS_VCLEANUP_INDEX QUICKTHREADS_ARG_INDEX(3)
+
+#endif /* ndef QUICKTHREADS_POWERPC_H */
+
diff --git a/ext/systemc/src/sysc/qt/md/powerpc_sys5.s b/ext/systemc/src/sysc/qt/md/powerpc_sys5.s
new file mode 100644
index 000000000..d9dc9332d
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/powerpc_sys5.s
@@ -0,0 +1,639 @@
+/* powerpc-sys5.s -- assembly support. */
+
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+
+
+ * PowerPC-System V thread switching module.
+ *
+ * This software is largely based on the original PowerPC-Linux porting
+ * developed by Ken Aaker <kenaaker@silverbacksystems.com>
+ *
+ * Marco Bucci <marco.bucci@inwind.it>
+ * December 2002
+ *
+ */
+
+
+/*
+ *
+ * PowerPC Register convections:
+ *
+ * r0 volatile
+ * r1 SP
+ * r2 system reserved
+ * r3-r4 volatile for parameter passing and function return
+ * r5-r10 volatile for parameter passing
+ * r11-r12 volatile
+ * r13-r14 non volatile registers
+ * f0 volatile
+ * f1 volatile for parameter passing and function return
+ * f2-f13 volatile for parameter passing
+ * f14-f31 non volatile
+ *
+ * cr2-cr4 non volatile
+ *
+ *
+ * See on the heather file for more documentation.
+ *
+ *
+ *
+ * IMPLEMENTATION NOTES
+ *
+ *
+ * 1) Condition register saving
+ * On most machines, the condition code register is caller-save.
+ * On the PPC, the condition code register is callee-save, so the
+ * thread context switch must preserve it.
+ *
+ *
+ * 2) Floating point registers saving
+ * On resuming a thread, floating point registers are or not restored just
+ * depending on which block routine suspended the thread (i.e. regardless
+ * whether "qt_block", "qt_blocki" or "qt_abort" is used to resume it).
+ * This behaviour is obtained by implementing "qt_block" by means af a nested
+ * call to "qt_blocki". As a result, the blocking of a thread always goes
+ * and returns through "qt_blocki and, if a thread was blocked by "qt_block",
+ * its execution resumes from the floating point restoring code on exit
+ * of "qt_block".
+ *
+ * Thanks to David Keppel that explained me this "simple" trick.
+ *
+ *
+ * 3) C languace code debugging
+ * The original version of this software was developed and debugged under
+ * MacOS X using the Metrowerks Code Warrior PPC integrated assembler.
+ * It could be still used with a C inline assembler by means of a suitable
+ * file to include it.
+ * In order to avoid "copy and paste" bugs, and make easyer the maintaining,
+ * I made the minimal changes, so you can find some strange code as:
+ *
+ * #if 0
+ * .if 0
+ * C code here
+ * .endif
+ * #endif
+ *
+ * This is just to embed some C code that is needed by the Code Warrior
+ * integrated assembler.
+ *
+ *
+ * 4) Assembly constants generation
+ * Constants used in the assembly code are generated by running
+ * the C code in the sequel (commented). It uses the C macros declared in
+ * the C heather in order to guarantee that the C interface and the assebly
+ * code are "aligned". I avoided the use of an assebler preprocessor since
+ * they are not so standard and moreover using macro espressions makes the
+ * assembly debugging more difficult.
+ *
+ *
+
+
+#include <iostream>
+#include "powerpc_sys5.h"
+
+int main()
+{
+ using namespace std;
+
+ int i;
+
+ cout << ".set LR_SAVE, " << PPC_LR_SAVE << endl;
+ cout << ".set BLOCKI_FSIZE, " << QUICKTHREADS_BLOCKI_FRAME_SIZE << endl;
+ cout << ".set BLOCKI_CR_SAVE, " << QUICKTHREADS_BLOCKI_CR_SAVE << endl;
+ cout << ".set BLOCK_FSIZE, " << QUICKTHREADS_BLOCK_FRAME_SIZE << endl;
+
+ cout << endl;
+ for(i=0; i<12; i++)
+ cout << ".set PAR_" << i << ", " << PPC_PAR(i) << endl;
+
+ cout << endl;
+ i = 13;
+ cout << ".set GPR_SAVE_" << i << ", " << QUICKTHREADS_BLOCKI_GPR_SAVE(i) << endl;
+
+ cout << endl;
+ for(i=31; i>13; i--)
+ cout << ".set FPR_SAVE_" << i << ", " << QUICKTHREADS_BLOCK_FPR_SAVE(i) << endl;
+
+ cout << endl;
+ cout << ".set VARGS_BKOFF, " << QUICKTHREADS_VARGS_BKOFF << endl;
+
+
+ cout << endl << endl << endl;
+
+ for(i=31; i>13; i--)
+ cout << "\tstfd\tf" << i << ",FPR_SAVE_" << i << "(%r1)" << endl;
+
+ cout << endl;
+ for(i=31; i>13; i--)
+ cout << "\tlfd \tf" << i << ",FPR_SAVE_" << i << "(%r1)" << endl;
+
+ cout << endl << endl << endl;
+
+
+ return 0;
+}
+
+
+
+ *
+ *
+ *
+ */
+
+
+#if 0
+
+ .text
+ .align 4
+
+ .globl qt_block
+ .globl _qt_block
+ .globl qt_blocki
+ .globl _qt_blocki
+ .globl qt_abort
+ .globl _qt_abort
+ .globl qt_start
+ .globl _qt_start
+ .globl qt_vstart
+ .globl _qt_vstart
+
+
+.set LR_SAVE, 4
+.set BLOCKI_FSIZE, 96
+.set BLOCKI_CR_SAVE, 8 /* CR is saved into the callee's stack frame */
+.set BLOCK_FSIZE, 160
+
+.set PAR_0, 8
+.set PAR_1, 12
+.set PAR_2, 16
+.set PAR_3, 20
+.set PAR_4, 24
+.set PAR_5, 28
+.set PAR_6, 32
+.set PAR_7, 36
+.set PAR_8, 40
+.set PAR_9, 44
+.set PAR_10, 48
+.set PAR_11, 52
+
+.set GPR_SAVE_13, 20
+
+.set FPR_SAVE_31, 152
+.set FPR_SAVE_30, 144
+.set FPR_SAVE_29, 136
+.set FPR_SAVE_28, 128
+.set FPR_SAVE_27, 120
+.set FPR_SAVE_26, 112
+.set FPR_SAVE_25, 104
+.set FPR_SAVE_24, 96
+.set FPR_SAVE_23, 88
+.set FPR_SAVE_22, 80
+.set FPR_SAVE_21, 72
+.set FPR_SAVE_20, 64
+.set FPR_SAVE_19, 56
+.set FPR_SAVE_18, 48
+.set FPR_SAVE_17, 40
+.set FPR_SAVE_16, 32
+.set FPR_SAVE_15, 24
+.set FPR_SAVE_14, 16
+
+
+
+
+/* various offsets used by "qt_varg" */
+.set P_T, PAR_0
+.set P_STARTUP, PAR_1
+.set P_USERF, PAR_2
+.set P_CLEANUP, PAR_3
+ /* the offset used to move back the linkage area to be adiacent to
+ * the variant argument list before calling "userf(...).
+ * Skip "t", "startup", "userf", "cleanup" and first
+ * 8 parameters (since they are passed via registers) */
+.set VARGS_BKOFF, 48
+
+ /* location where "t" and "cleanup" are saved (with respect of
+ * the stack frame base) */
+.set P_T_SAVE, -4
+.set P_CLEANUP_SAVE, -8
+
+#endif
+
+
+
+/* Block the current thread saving all integer non volatile registers and
+ * start a new thread.
+ */
+#if 0
+.if 0
+#endif
+void *qt_blocki (void *helper, void *a0, void *a1, void *newthread);
+asm void *qt_blocki (void *helper, void *a0, void *a1, void *newthread)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+qt_blocki:
+_qt_blocki:
+#endif
+/* prolog code */
+ stwu %r1,-BLOCKI_FSIZE(%r1) /* allocate the stack frame */
+ mflr %r0 /* return addr in r0 */
+ mfcr %r11 /* CR in r11 */
+ stw %r0,LR_SAVE+BLOCKI_FSIZE(%r1) /* save return addr in the stack */
+ stw %r11,BLOCKI_CR_SAVE(%r1) /* save CR in the stack */
+ stmw %r13,GPR_SAVE_13(%r1) /* save non-volatile reg */
+
+/* call helper(qt_t *old, void *a0, void *a1) */
+ mtlr %r3 /* "helper" addr in the link reg */
+ mr %r3,%r1 /* current thread (i.e. the SP) in arg "old" */
+ mr %r1,%r6 /* swap to the new thread (i.e. to its SP) */
+ blrl /* jump to "helper" */
+/* the "helper" return value is returned (since r3 is not changed) */
+
+/* epilog code: return to the new thread's "qt_blocki" caller */
+ lmw %r13,GPR_SAVE_13(%r1) /* restore non-volatile reg */
+ lwz %r0,LR_SAVE+BLOCKI_FSIZE(%r1) /* recover return addr */
+ lwz %r11,BLOCKI_CR_SAVE(%r1) /* recover CR */
+ mtlr %r0 /* return address in the link reg */
+ mtcr %r11 /* restore CR */
+ addi %r1,%r1,BLOCKI_FSIZE /* free the stack frame */
+ blr /* return */
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+/* Abort the current thread and start a new thread.
+ */
+#if 0
+.if 0
+#endif
+void qt_abort (void *helper, void *a0, void *a1, void *newthread);
+asm void qt_abort (void *helper, void *a0, void *a1, void *newthread)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+qt_abort:
+_qt_abort:
+#endif
+/* prolog code */
+/* there is no prolog. It will never come back */
+
+/* call helper(qt_t *old, void *a0, void *a1) */
+ mtlr %r3 /* "helper" addr in the link reg */
+ mr %r1,%r6 /* swap to the new thread (i.e. to its SP) */
+/* we don't need to set "old", we can pass just garbage. Actually, since r3
+ is not changed, "old" is set to "helper" (don't care) */
+ blrl /* call "helper" */
+/* the "helper" return value is returned (since r3 is not changed) */
+
+/* epilog code: return to the new thread's "qt_blocki" caller */
+ lmw %r13,GPR_SAVE_13(%r1) /* restore non-volatile reg */
+ lwz %r0,LR_SAVE+BLOCKI_FSIZE(%r1) /* recover return addr */
+ lwz %r11,BLOCKI_CR_SAVE(%r1) /* recover CR */
+ mtlr %r0 /* return address in the link reg */
+ mtcr %r11 /* restore CR */
+ addi %r1,%r1,BLOCKI_FSIZE /* free the stack frame */
+ blr /* return */
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+/* Block the current thread saving all non volatile registers and start
+ * a new thread.
+ */
+#if 0
+.if 0
+#endif
+void *qt_block (void *helper, void *a0, void *a1, void *newthread);
+asm void *qt_block (void *helper, void *a0, void *a1, void *newthread)
+{
+#if 0
+.endif
+#endif
+
+# if 0
+qt_block:
+_qt_block:
+#endif
+/* prolog code */
+ stwu %r1,-BLOCK_FSIZE(%r1) /* allocate the stack frame */
+ mflr %r0 /* return addr in r0 */
+ stw %r0,LR_SAVE+BLOCK_FSIZE(%r1) /* save return addr in the stack */
+
+/* save non-volatile fp reg */
+ stfd %f31,FPR_SAVE_31(%r1)
+ stfd %f30,FPR_SAVE_30(%r1)
+ stfd %f29,FPR_SAVE_29(%r1)
+ stfd %f28,FPR_SAVE_28(%r1)
+ stfd %f27,FPR_SAVE_27(%r1)
+ stfd %f26,FPR_SAVE_26(%r1)
+ stfd %f25,FPR_SAVE_25(%r1)
+ stfd %f24,FPR_SAVE_24(%r1)
+ stfd %f23,FPR_SAVE_23(%r1)
+ stfd %f22,FPR_SAVE_22(%r1)
+ stfd %f21,FPR_SAVE_21(%r1)
+ stfd %f20,FPR_SAVE_20(%r1)
+ stfd %f19,FPR_SAVE_19(%r1)
+ stfd %f18,FPR_SAVE_18(%r1)
+ stfd %f17,FPR_SAVE_17(%r1)
+ stfd %f16,FPR_SAVE_16(%r1)
+ stfd %f15,FPR_SAVE_15(%r1)
+ stfd %f14,FPR_SAVE_14(%r1)
+/* block the thread */
+ bl qt_blocki
+/* the thread is going to be resumed */
+/* restore non-volatile fp reg */
+ lfd %f31,FPR_SAVE_31(%r1)
+ lfd %f30,FPR_SAVE_30(%r1)
+ lfd %f29,FPR_SAVE_29(%r1)
+ lfd %f28,FPR_SAVE_28(%r1)
+ lfd %f27,FPR_SAVE_27(%r1)
+ lfd %f26,FPR_SAVE_26(%r1)
+ lfd %f25,FPR_SAVE_25(%r1)
+ lfd %f24,FPR_SAVE_24(%r1)
+ lfd %f23,FPR_SAVE_23(%r1)
+ lfd %f22,FPR_SAVE_22(%r1)
+ lfd %f21,FPR_SAVE_21(%r1)
+ lfd %f20,FPR_SAVE_20(%r1)
+ lfd %f19,FPR_SAVE_19(%r1)
+ lfd %f18,FPR_SAVE_18(%r1)
+ lfd %f17,FPR_SAVE_17(%r1)
+ lfd %f16,FPR_SAVE_16(%r1)
+ lfd %f15,FPR_SAVE_15(%r1)
+ lfd %f14,FPR_SAVE_14(%r1)
+
+ lwz %r0,LR_SAVE+BLOCK_FSIZE(%r1) /* recover return addr */
+ mtlr %r0 /* return address in the link reg */
+ addi %r1,%r1,BLOCK_FSIZE /* free the stack frame */
+ blr /* return */
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+/* Start a single argument thread using parameters preloaded in the stack
+ * during thread initialization (see comments on stack initialization in the
+ * heather file).
+ *
+ * Executes:
+ *
+ * only(u, t, userf);
+ */
+#if 0
+.if 0
+#endif
+void qt_start(void);
+asm void qt_start(void)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+qt_start:
+_qt_start:
+#endif
+ lwz %r3,PAR_0(%r1) /* "u" in r3 */
+ lwz %r4,PAR_1(%r1) /* "t" in r4 */
+ lwz %r5,PAR_2(%r1) /* "userf" in r5 */
+ lwz %r6,PAR_3(%r1) /* "only" in r6 */
+ mtlr %r6 /* "only" address in the link reg */
+/* call only(u, t, userf) */
+ blrl /* jump to "only" */
+/* error if it returns */
+ b qt_error
+/* dead code (some inline asm "wants" the epilog, or they genetare it) */
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+/* Start a variant argument thread using parameters preloaded in the stack
+ * during thread initialization (see comments on stack initialization in the
+ * heather file).
+ *
+ * Executes:
+ *
+ * startup(t);
+ * userf_return = userf(...);
+ * cleanup(pt, userf_return);
+ *
+
+
+ ***** Stack layout on start *****
+
+
+ backchain -> STACK BOTTOM (higher address)
+ +==========================+
+ backchain - 4 -> | |
+ + LOCAL VARIABLES AREA +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ | | arg(n)
+ + +
+ | |
+ + VARIABLE ARGUMENT LIST +
+ ..............
+ + for userf call +
+ SP + PAR(5) -> | | arg(1)
+ + +
+ SP + PAR(4) -> | | arg(0)
+ +--------------------------+
+ SP + PAR(3) -> | | cleanup par
+ + +
+ SP + PAR(2) -> | | userf par
+ + PARAMETER AREA +
+ SP + PAR(1) -> | | startup par
+ + +
+ SP + PAR(0) -> | | t par
+ +--------------------------+
+ | |
+ + LINKAGE AREA +
+ SP -> | |
+ +==========================+
+ STACK TOP (lower address)
+
+ Stack grows down
+ |
+ V
+
+
+
+ ***** Stack layout before call userf *****
+
+
+ backchain -> STACK BOTTOM (higher address)
+ +==========================+
+ backchain - 4 -> | |
+ + LOCAL VARIABLES AREA +
+ ..............
+ + +
+ | |
+ +--------------------------+
+ | |
+ + ALIGNMEBNT PAD +
+ ..............
+ + (if needed) +
+ | |
+ +--------------------------+
+ | | arg(n)
+ + +
+ | |
+ + VARIABLE ARGUMENT LIST +
+ ..............
+ + for userf call +
+ SP + PAR(1) -> | | arg(1)
+ + +
+ SP + PAR(0) -> | | arg(0)
+ +--------------------------+
+ | |
+ + LINKAGE AREA +
+ SP -> | |
+ +==========================+
+ STACK TOP (lower address)
+
+ Stack grows down
+ |
+ V
+
+
+ * To call "userf(...)", the argument list must be adiacent to the linkage
+ * area. Instead of copy the argument list, we move back the linkage area
+ * (actually, we just increase the SP and copy the backchain). "t" and
+ * "cleanup" are saved in a local variable area in order to call
+ * cleanup(pt, userf_return).
+
+*/
+
+
+#if 0
+.if 0
+#endif
+void qt_vstart(void);
+asm void qt_vstart(void)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+qt_vstart:
+_qt_vstart:
+#endif
+/* NOTICE: the callee routines could save parameter registers in the caller's
+ * stack parameter area. We put "t" in PAR(0) in such a way, if startup(t)
+ * will save "t", it will be saved on the same location thus not delething
+ * any other parameter.
+ */
+
+/* since we will move back the linckage area (to make it adiacent to the
+ * parameter list), we need to save "t" and "cleanup". We have made room for
+ * this on the bottom of the stack frame. */
+
+/* save parameters in the local variable area */
+ lwz %r11,0(%r1) /* get the backchain */
+ lwz %r3,P_T(%r1)
+ lwz %r4,P_CLEANUP(%r1)
+ stw %r3,P_T_SAVE(%r11) /* save "pt" */
+ stw %r4,P_CLEANUP_SAVE(%r11) /* save "cleanup" */
+
+/* call startup(t) */
+ lwz %r5,P_STARTUP(%r1)
+ mtlr %r5
+ blrl /* call "startup" */
+
+/* call userf(...) */
+ lwz %r11,0(%r1) /* reload backchain (r11 is volatile) */
+ lwz %r4,P_USERF(%r1) /* load "userf" */
+ mtlr %r4
+
+ /* first eight parameter of the variant list must be copyed in
+ * GPR3-GPR10. There is a four places offset due to "t", "startup",
+ * userf" and "cleanup" */
+
+ lwz %r3,PAR_4(%r1)
+ lwz %r4,PAR_5(%r1)
+ lwz %r5,PAR_6(%r1)
+ lwz %r6,PAR_7(%r1)
+ lwz %r7,PAR_8(%r1)
+ lwz %r8,PAR_9(%r1)
+ lwz %r9,PAR_10(%r1)
+ lwz %r10,PAR_11(%r1)
+
+
+ /* move the linkage area to be adiacent to the argument list */
+ stw %r11,VARGS_BKOFF(%r1) /* copy backchain */
+ addi %r1,%r1,VARGS_BKOFF /* move back the stack */
+
+ blrl /* call "userf" */
+
+/* call qt_cleanup(void *pt, void *vuserf_return) */
+ lwz %r11,0(%r1) /* reload backchain (r11 is volatile) */
+
+ mr %r4,%r3 /* push "userf" return as 2nd parameter */
+ lwz %r3,P_T_SAVE(%r11) /* reload "pt" */
+ lwz %r5,P_CLEANUP_SAVE(%r11) /* reload "cleanup" */
+ mtlr %r5
+ blrl
+ b qt_error
+/* dead code (some inline asm "wants" the epilog, or they genetare it) */
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
diff --git a/ext/systemc/src/sysc/qt/md/powerpc_sys5_b.s b/ext/systemc/src/sysc/qt/md/powerpc_sys5_b.s
new file mode 100644
index 000000000..e57a20e2e
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/powerpc_sys5_b.s
@@ -0,0 +1,290 @@
+/* speed test for basic CPU operations */
+
+
+/* Marco Bucci <marco.bucci@inwind.it> */
+
+/* This code was developed with the Code Warrior integrate ppc assembler.
+ * Macros are use to hide illegal constructs whether you are using a
+ * "normal" assembler or the "C integrated" assembler.
+ */
+
+#if 0
+
+
+ .text
+ .align 4
+
+ .globl b_call_reg
+ .globl _b_call_reg
+ .globl b_call_imm
+ .globl _b_call_imm
+ .globl b_add
+ .globl _b_add
+ .globl b_load
+ .globl _b_load
+
+.set fsize, 64
+.set lrsave, 4
+
+#else
+
+#define fsize 64
+#define lrsave 4
+
+#endif
+
+
+
+
+#if 0
+.if 0
+#endif
+asm void b_null(void)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+b_null:
+#endif
+
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+/* actually the same as the following. How to get "b_null" address?
+ * I didnt find the right sintax or the right way.
+ * I should take the current PC, then the difference to "b_null"
+ * (making the difference beween the labels), perform the sum and go?!
+ */
+#if 0
+.if 0
+#endif
+asm void b_call_reg(long n)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+b_call_reg:
+_b_call_reg:
+#endif
+
+ mflr %r0
+ stw %r31,-4(%r1)
+ stw %r30,-8(%r1)
+ stw %r0,lrsave(%r1)
+ stwu %r1,-fsize(%r1)
+ mr %r30,%r3
+ li %r31,0
+
+ b L1
+L0:
+ bl b_null
+ bl b_null
+ bl b_null
+ bl b_null
+ bl b_null
+
+ addi %r31,%r31,5
+L1:
+ cmpw %r31,%r30
+ blt L0
+
+
+ lwz %r0,lrsave+fsize(%r1)
+ mtlr %r0
+ lwz %r31,-4+fsize(%r1)
+ lwz %r30,-8+fsize(%r1)
+ addi %r1,%r1,fsize
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+
+#if 0
+.if 0
+#endif
+asm void b_call_imm(long n)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+b_call_imm:
+_b_call_imm:
+#endif
+
+ mflr %r0
+ stw %r31,-4(%r1)
+ stw %r30,-8(%r1)
+ stw %r0,lrsave(%r1)
+ stwu %r1,-fsize(%r1)
+ mr %r30,%r3
+ li %r31,0
+
+ b L3
+L2:
+ bl b_null
+ bl b_null
+ bl b_null
+ bl b_null
+ bl b_null
+
+ addi %r31,%r31,5
+L3:
+ cmpw %r31,%r30
+ blt L2
+
+
+ lwz %r0,lrsave+fsize(%r1)
+ mtlr %r0
+ lwz %r31,-4+fsize(%r1)
+ lwz %r30,-8+fsize(%r1)
+ addi %r1,%r1,fsize
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+#if 0
+.if 0
+#endif
+asm void b_add(long n)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+b_add:
+_b_add:
+#endif
+
+ mflr %r0
+ stw %r31,-4(%r1)
+ stw %r30,-8(%r1)
+ stw %r0,lrsave(%r1)
+ stwu %r1,-fsize(%r1)
+ mr %r30,%r3
+ li %r31,0
+
+ b L5
+L4:
+ addi %r3,%r3,5
+ addi %r4,%r4,5
+ addi %r5,%r5,5
+ addi %r6,%r6,5
+ addi %r7,%r7,5
+
+ addi %r3,%r3,5
+ addi %r4,%r4,5
+ addi %r5,%r5,5
+ addi %r6,%r6,5
+ addi %r7,%r7,5
+
+ addi %r31,%r31,10
+L5:
+ cmpw %r31,%r30
+ blt L4
+
+
+ lwz %r0,lrsave+fsize(%r1)
+ mtlr %r0
+ lwz %r31,-4+fsize(%r1)
+ lwz %r30,-8+fsize(%r1)
+ addi %r1,%r1,fsize
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
+
+
+
+#if 0
+.if 0
+#endif
+asm void b_load(long n)
+{
+#if 0
+.endif
+#endif
+
+#if 0
+b_load:
+_b_load:
+#endif
+
+ mflr %r0
+ stw %r31,-4(%r1)
+ stw %r30,-8(%r1)
+ stw %r0,lrsave(%r1)
+ stwu %r1,-fsize(%r1)
+ mr %r30,%r3
+ li %r31,0
+
+ b L7
+L6:
+ lwz %r3,4(%r1)
+ lwz %r4,8(%r1)
+ lwz %r5,12(%r1)
+ lwz %r6,16(%r1)
+ lwz %r7,20(%r1)
+
+ lwz %r3,24(%r1)
+ lwz %r4,28(%r1)
+ lwz %r5,32(%r1)
+ lwz %r6,36(%r1)
+ lwz %r7,40(%r1)
+
+
+ addi %r31,%r31,10
+L7:
+ cmpw %r31,%r30
+ blt L6
+
+
+ lwz %r0,lrsave+fsize(%r1)
+ mtlr %r0
+ lwz %r31,-4+fsize(%r1)
+ lwz %r30,-8+fsize(%r1)
+ addi %r1,%r1,fsize
+ blr
+
+#if 0
+.if 0
+#endif
+}
+#if 0
+.endif
+#endif
diff --git a/ext/systemc/src/sysc/qt/md/pthreads.Makefile b/ext/systemc/src/sysc/qt/md/pthreads.Makefile
new file mode 100644
index 000000000..f722fbe19
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/pthreads.Makefile
@@ -0,0 +1,108 @@
+# Generated automatically from Makefile.in by configure.
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = /bin/sh
+
+all:
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+mostlyclean-compile:
+
+clean-compile:
+
+distclean-compile:
+
+maintainer-clean-compile:
+
+tags:
+
+ID:
+
+TAGS:
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+
+maintainer-clean-tags:
+
+distdir:
+
+info-am:
+info:
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am: install-data-local
+install-data: install-data-am
+
+install-am: all-am
+install: install-am
+uninstall-am: uninstall-local
+uninstall: uninstall-am
+all-am:
+all-redirect:
+install-strip:
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+
+maintainer-clean-generic:
+mostlyclean-am:
+
+mostlyclean:
+
+clean-am:
+
+clean:
+
+distclean-am:
+
+distclean:
+
+maintainer-clean-am:
+
+maintainer-clean:
+
+.PHONY:
+
+
+configuration:
+
+clean:
+
+install-data-local:
+
+uninstall-local:
+
diff --git a/ext/systemc/src/sysc/qt/md/solaris.README b/ext/systemc/src/sysc/qt/md/solaris.README
new file mode 100644
index 000000000..04f855c44
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/solaris.README
@@ -0,0 +1,19 @@
+Solaris 2.x is like System V (maybe it *is* System V?) and is different
+from older versions in that it uses no leading underscore for variable
+and function names. That is, the old convention was:
+
+ foo(){}
+
+got compiled as
+
+ .globl _foo
+ _foo:
+
+and is now compiled as
+
+ .globl foo
+ foo:
+
+The `config' script should fix up the older (leading underscore) versions
+of the machine-dependent files to use the newer (no leading underscore)
+calling conventions.
diff --git a/ext/systemc/src/sysc/qt/md/sparc.h b/ext/systemc/src/sysc/qt/md/sparc.h
new file mode 100644
index 000000000..edaf5325e
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/sparc.h
@@ -0,0 +1,140 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+#ifndef QUICKTHREADS_SPARC_H
+#define QUICKTHREADS_SPARC_H
+
+typedef unsigned long qt_word_t;
+
+/* Stack layout on the sparc:
+
+ non-varargs:
+
+ +---
+ | <blank space for alignment>
+ | %o7 == return address -> qt_start
+ | %i7
+ | %i6 == frame pointer -> 0 (NULL-terminated stack frame chain)
+ | %i5 -> only
+ | %i4 -> userf
+ | %i3
+ | %i2 -> pt
+ | %i1 -> pu
+ | %i0
+ | %l7
+ | %l6
+ | %l5
+ | %l4
+ | %l3
+ | %l2
+ | %l1
+ | %l0 <--- qt_t.sp
+ +---
+
+ varargs:
+
+ | :
+ | :
+ | argument list
+ | one-word aggregate return pointer
+ +---
+ | <blank space for alignment>
+ | %o7 == return address -> qt_vstart
+ | %i7
+ | %i6 == frame pointer -> 0 (NULL-terminated stack frame chain)
+ | %i5 -> startup
+ | %i4 -> userf
+ | %i3 -> cleanup
+ | %i2 -> pt
+ | %i1
+ | %i0
+ | %l7
+ | %l6
+ | %l5
+ | %l4
+ | %l3
+ | %l2
+ | %l1
+ | %l0 <--- qt_t.sp
+ +---
+
+ */
+
+
+/* What to do to start a thread running. */
+extern void qt_start (void);
+extern void qt_vstart (void);
+
+
+/* Hold 17 saved registers + 1 word for alignment. */
+#define QUICKTHREADS_STKBASE (18 * 4)
+#define QUICKTHREADS_VSTKBASE QUICKTHREADS_STKBASE
+
+
+/* Stack must be doubleword aligned. */
+#define QUICKTHREADS_STKALIGN (8) /* Doubleword aligned. */
+
+#define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_I5)
+#define QUICKTHREADS_USER_INDEX (QUICKTHREADS_I4)
+#define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_I2)
+#define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_I1)
+
+#define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_I5)
+#define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_I4)
+#define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_I3)
+#define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_I2)
+
+#define QUICKTHREADS_O7 (16)
+#define QUICKTHREADS_I6 (14)
+#define QUICKTHREADS_I5 (13)
+#define QUICKTHREADS_I4 (12)
+#define QUICKTHREADS_I3 (11)
+#define QUICKTHREADS_I2 (10)
+#define QUICKTHREADS_I1 ( 9)
+
+
+/* The thread will ``return'' to the `qt_start' routine to get things
+ going. The normal return sequence takes us to QUICKTHREADS_O7+8, so we
+ pre-subtract 8. The frame pointer chain is 0-terminated to prevent
+ the trap handler from chasing off in to random memory when flushing
+ stack windows. */
+
+#define QUICKTHREADS_ARGS_MD(top) \
+ (QUICKTHREADS_SPUT ((top), QUICKTHREADS_O7, ((void *)(((int)qt_start)-8))), \
+ QUICKTHREADS_SPUT ((top), QUICKTHREADS_I6, 0))
+
+
+/* The varargs startup routine always reads 6 words of arguments
+ (6 argument registers) from the stack, offset by one word to
+ allow for an aggregate return area pointer. If the varargs
+ routine actually pushed fewer words than that, qt_vstart could read
+ off the top of the stack. To prevent errors, we always allocate 8
+ words. The space is often just wasted. */
+
+#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \
+ ((qt_t *)(((char *)(sp)) - 8*4 - QUICKTHREADS_STKROUNDUP(vabytes)))
+
+#define QUICKTHREADS_VARGS_MD1(sp) \
+ (QUICKTHREADS_SPUT (sp, QUICKTHREADS_O7, ((void *)(((int)qt_vstart)-8))))
+
+/* The SPARC has wierdo calling conventions which stores a hidden
+ parameter for returning aggregate values, so the rest of the
+ parameters are shoved up the stack by one place. */
+#define QUICKTHREADS_VARGS_ADJUST(sp) (((char *)sp)+4)
+
+#define QUICKTHREADS_VARGS_DEFAULT
+
+
+#define QUICKTHREADS_GROW_DOWN
+
+#endif /* ndef QUICKTHREADS_SPARC_H */
diff --git a/ext/systemc/src/sysc/qt/md/sparc.s b/ext/systemc/src/sysc/qt/md/sparc.s
new file mode 100644
index 000000000..d61236b54
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/sparc.s
@@ -0,0 +1,142 @@
+/* sparc.s -- assembly support for the `qt' thread building kit. */
+
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+/* #include <machine/trap.h> */
+
+ .text
+ .align 4
+ .global _qt_blocki
+ .global _qt_block
+ .global _qt_abort
+ .global _qt_start
+ .global _qt_vstart
+
+/* Register assignment:
+// %o0: incoming `helper' function to call after cswap
+// also used as outgoing sp of old thread (qt_t *)
+// %o1, %o2:
+// parameters to `helper' function called after cswap
+// %o3: sp of new thread
+// %o5: tmp used to save old thread sp, while using %o0
+// to call `helper' f() after cswap.
+//
+//
+// Aborting a thread is easy if there are no cached register window
+// frames: just switch to the new stack and away we go. If there are
+// cached register window frames they must all be written back to the
+// old stack before we move to the new stack. If we fail to do the
+// writeback then the old stack memory can be written with register
+// window contents e.g., after the stack memory has been freed and
+// reused.
+//
+// If you don't believe this, try setting the frame pointer to zero
+// once we're on the new stack. This will not affect correctnes
+// otherwise because the frame pointer will eventually get reloaded w/
+// the new thread's frame pointer. But it will be zero briefly before
+// the reload. You will eventually (100,000 cswaps later on a small
+// SPARC machine that I tried) get an illegal instruction trap from
+// the kernel trying to flush a cached window to location 0x0.
+//
+// Solution: flush windows before switching stacks, which invalidates
+// all the other register windows. We could do the trap
+// conditionally: if we're in the lowest frame of a thread, the fp is
+// zero already so we know there's nothing cached. But we expect most
+// aborts will be done from a first function that does a `save', so we
+// will rarely save anything and always pay the cost of testing to see
+// if we should flush.
+//
+// All floating-point registers are caller-save, so this routine
+// doesn't need to do anything to save and restore them.
+//
+// `qt_block' and `qt_blocki' return the same value as the value
+// returned by the helper function. We get this ``for free''
+// since we don't touch the return value register between the
+// return from the helper function and return from qt_block{,i}.
+*/
+
+_qt_block:
+_qt_blocki:
+ sub %sp, 8, %sp /* Allocate save area for return pc. */
+ st %o7, [%sp+64] /* Save return pc. */
+_qt_abort:
+ ta 0x03 /* Save locals and ins. */
+ mov %sp, %o5 /* Remember old sp w/o chng ins/locals. */
+ sub %o3, 96, %sp /* Allocate kwsa, switch stacks. */
+ call %o0, 0 /* Call `helper' routine. */
+ mov %o5, %o0 /* Pass old thread to qt_after_t() */
+ /* .. along w/ args in %o1 & %o2. */
+
+ /* Restore callee-save regs. The kwsa
+ // is on this stack, so offset all
+ // loads by sizeof(kwsa), 64 bytes.
+ */
+ ldd [%sp+ 0+96], %l0
+ ldd [%sp+ 8+96], %l2
+ ldd [%sp+16+96], %l4
+ ldd [%sp+24+96], %l6
+ ldd [%sp+32+96], %i0
+ ldd [%sp+40+96], %i2
+ ldd [%sp+48+96], %i4
+ ldd [%sp+56+96], %i6
+ ld [%sp+64+96], %o7 /* Restore return pc. */
+
+ retl /* Return to address in %o7. */
+ add %sp, 104, %sp /* Deallocate kwsa, ret pc area. */
+
+
+/* The function calling conventions say there has to be a 1-word area
+// in the caller's stack to hold a pointer to space for aggregate
+// return values. It also says there should be a 6-word area to hold
+// %o0..%o5 if the callee wants to save them (why? I don't know...)
+// Round up to 8 words to maintain alignment.
+//
+// Parameter values were stored in callee-save regs and are moved to
+// the parameter registers.
+*/
+_qt_start:
+ mov %i1, %o0 /* `pu': Set up args to `only'. */
+ mov %i2, %o1 /* `pt'. */
+ mov %i4, %o2 /* `userf'. */
+ call %i5, 0 /* Call client function. */
+ sub %sp, 32, %sp /* Allocate 6-word callee space. */
+
+ call _qt_error, 0 /* `only' erroniously returned. */
+ nop
+
+
+/* Same comments as `_qt_start' about allocating rounded-up 7-word
+// save areas. */
+
+_qt_vstart:
+ sub %sp, 32, %sp /* Allocate 7-word callee space. */
+ call %i5, 0 /* call `startup'. */
+ mov %i2, %o0 /* .. with argument `pt'. */
+
+ add %sp, 32, %sp /* Use 7-word space in varargs. */
+ ld [%sp+ 4+64], %o0 /* Load arg0 ... */
+ ld [%sp+ 8+64], %o1
+ ld [%sp+12+64], %o2
+ ld [%sp+16+64], %o3
+ ld [%sp+20+64], %o4
+ call %i4, 0 /* Call `userf'. */
+ ld [%sp+24+64], %o5
+
+ /* Use 6-word space in varargs. */
+ mov %o0, %o1 /* Pass return value from userf */
+ call %i3, 0 /* .. when call `cleanup. */
+ mov %i2, %o0 /* .. along with argument `pt'. */
+
+ call _qt_error, 0 /* `cleanup' erroniously returned. */
+ nop
diff --git a/ext/systemc/src/sysc/qt/md/sparc_b.s b/ext/systemc/src/sysc/qt/md/sparc_b.s
new file mode 100644
index 000000000..cd26672d7
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/sparc_b.s
@@ -0,0 +1,106 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+ .globl _b_call_reg
+ .globl _b_call_imm
+ .globl _b_add
+ .globl _b_load
+
+_b_null:
+ retl
+ nop
+
+_b_call_reg:
+ sethi %hi(_b_null),%o4
+ or %o4,%lo(_b_null),%o4
+ add %o7,%g0, %o3
+L0:
+ call %o4
+ nop
+ call %o4
+ nop
+ call %o4
+ nop
+ call %o4
+ nop
+ call %o4
+ nop
+
+ subcc %o0,1,%o0
+ bg L0
+ nop
+ add %o3,%g0, %o7
+ retl
+ nop
+
+_b_call_imm:
+ sethi %hi(_b_null),%o4
+ or %o4,%lo(_b_null),%o4
+ add %o7,%g0, %o3
+L1:
+ call _b_null
+ call _b_null
+ call _b_null
+ call _b_null
+ call _b_null
+
+ subcc %o0,1,%o0
+ bg L0
+ nop
+ add %o3,%g0, %o7
+ retl
+ nop
+
+
+_b_add:
+ add %o0,%g0,%o1
+ add %o0,%g0,%o2
+ add %o0,%g0,%o3
+ add %o0,%g0,%o4
+L2:
+ sub %o0,5,%o0
+ sub %o1,5,%o1
+ sub %o2,5,%o2
+ sub %o3,5,%o3
+ sub %o4,5,%o4
+
+ subcc %o0,5,%o0
+ sub %o1,5,%o1
+ sub %o2,5,%o2
+ sub %o3,5,%o3
+ sub %o4,5,%o4
+
+ bg L2
+ nop
+ retl
+ nop
+
+
+_b_load:
+ ld [%sp+ 0], %g0
+L3:
+ ld [%sp+ 4],%g0
+ ld [%sp+ 8],%g0
+ ld [%sp+12],%g0
+ ld [%sp+16],%g0
+ ld [%sp+20],%g0
+ ld [%sp+24],%g0
+ ld [%sp+28],%g0
+ ld [%sp+32],%g0
+ ld [%sp+36],%g0
+
+ subcc %o0,10,%o0
+ bg L3
+ ld [%sp+ 0],%g0
+ retl
+ nop
diff --git a/ext/systemc/src/sysc/qt/md/vax.h b/ext/systemc/src/sysc/qt/md/vax.h
new file mode 100644
index 000000000..1948c6fbd
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/vax.h
@@ -0,0 +1,130 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+#ifndef QUICKTHREADS_VAX_H
+#define QUICKTHREADS_VAX_H
+
+typedef unsigned long qt_word_t;
+
+/* Thread's initial stack layout on the VAX:
+
+ non-varargs:
+
+ +---
+ | arg[2] === `userf' on startup
+ | arg[1] === `pt' on startup
+ | arg[0] === `pu' on startup
+ | ... === `only' on startup.
+ +---
+ | ret pc === `qt_start' on startup
+ | fp === 0 on startup
+ | ap === 0 on startup
+ | <mask>
+ | 0 (handler) <--- qt_t.sp
+ +---
+
+ When a non-varargs thread is started, it ``returns'' to the start
+ routine, which calls the client's `only' function.
+
+ The varargs case is clearly bad code. The various values should be
+ stored in a save area and snarfed in to callee-save registers on
+ startup. However, it's too painful to figure out the register
+ mask (right now), so do it the slow way.
+
+ +---
+ | arg[n-1]
+ | ..
+ | arg[0]
+ | nargs
+ +---
+ | === `cleanup'
+ | === `vuserf'
+ | === `startup'
+ | === `pt'
+ +---
+ | ret pc === `qt_start' on startup
+ | fp === 0 on startup
+ | ap === 0 on startup
+ | <mask>
+ | 0 (handler) <--- qt_t.sp
+ +---
+
+ When a varargs thread is started, it ``returns'' to the `qt_vstart'
+ startup code. The startup code pops all the extra arguments, then
+ calls the appropriate functions. */
+
+
+/* What to do to start a thread running. */
+extern void qt_start (void);
+extern void qt_vstart (void);
+
+
+/* Initial call frame for non-varargs and varargs cases. */
+#define QUICKTHREADS_STKBASE (10 * 4)
+#define QUICKTHREADS_VSTKBASE (9 * 4)
+
+
+/* Stack "must be" 4-byte aligned. (Actually, no, but it's
+ easiest and probably fastest to do so.) */
+
+#define QUICKTHREADS_STKALIGN (4)
+
+
+/* Where to place various arguments. */
+#define QUICKTHREADS_ONLY_INDEX (5)
+#define QUICKTHREADS_USER_INDEX (8)
+#define QUICKTHREADS_ARGT_INDEX (7)
+#define QUICKTHREADS_ARGU_INDEX (6)
+
+#define QUICKTHREADS_VSTARTUP_INDEX (6)
+#define QUICKTHREADS_VUSERF_INDEX (7)
+#define QUICKTHREADS_VCLEANUP_INDEX (8)
+#define QUICKTHREADS_VARGT_INDEX (5)
+
+
+/* Stack grows down. The top of the stack is the first thing to
+ pop off (predecrement, postincrement). */
+#define QUICKTHREADS_GROW_DOWN
+
+
+extern void qt_error (void);
+
+#define QUICKTHREADS_VAX_GMASK_NOREGS (0)
+
+/* Push on the error return address, null termination to call chains,
+ number of arguments to `only', register save mask (save no
+ registers). */
+
+#define QUICKTHREADS_ARGS_MD(sto) \
+ (QUICKTHREADS_SPUT (sto, 0, 0), \
+ QUICKTHREADS_SPUT (sto, 1, QUICKTHREADS_VAX_GMASK_NOREGS), \
+ QUICKTHREADS_SPUT (sto, 2, 0), \
+ QUICKTHREADS_SPUT (sto, 3, 0), \
+ QUICKTHREADS_SPUT (sto, 4, qt_start))
+
+#define QUICKTHREADS_VARGS_MD0(sto, nbytes) \
+ (QUICKTHREADS_SPUT (sto, (-(nbytes)/4)-1, (nbytes)/4), \
+ ((char *)(((sto)-4) - QUICKTHREADS_STKROUNDUP(nbytes))))
+
+#define QUICKTHREADS_VARGS_ADJUST(sp) ((char *)sp + 4)
+
+#define QUICKTHREADS_VARGS_MD1(sto) \
+ (QUICKTHREADS_SPUT (sto, 0, 0), \
+ QUICKTHREADS_SPUT (sto, 1, QUICKTHREADS_VAX_GMASK_NOREGS), \
+ QUICKTHREADS_SPUT (sto, 2, 0), \
+ QUICKTHREADS_SPUT (sto, 3, 0), \
+ QUICKTHREADS_SPUT (sto, 4, qt_vstart))
+
+#define QUICKTHREADS_VARGS_DEFAULT
+
+#endif /* QUICKTHREADS_VAX_H */
diff --git a/ext/systemc/src/sysc/qt/md/vax.s b/ext/systemc/src/sysc/qt/md/vax.s
new file mode 100644
index 000000000..fed03f043
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/vax.s
@@ -0,0 +1,69 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+ .text
+
+ .globl _qt_abort
+ .globl _qt_block
+ .globl _qt_blocki
+ .globl _qt_start
+ .globl _qt_vstart
+
+
+/*
+// Calls to these routines have the signature
+//
+// void *block (func, arg1, arg2, newsp)
+//
+// Since the prologue saves 5 registers, nargs, pc, fp, ap, mask, and
+// a condition handler (at sp+0), the first argument is 40=4*10 bytes
+// offset from the stack pointer.
+*/
+_qt_block:
+_qt_blocki:
+_qt_abort:
+ .word 0x7c0 /* Callee-save mask: 5 registers. */
+ movl 56(sp),r1 /* Get stack pointer of new thread. */
+ movl 52(sp),-(r1) /* Push arg2 */
+ movl 48(sp),-(r1) /* Push arg1 */
+ movl sp,-(r1) /* Push arg0 */
+
+ movl 44(sp),r0 /* Get helper to call. */
+ movl r1,sp /* Move to new thread's stack. */
+ addl3 sp,$12,fp /* .. including the frame pointer. */
+ calls $3,(r0) /* Call helper. */
+
+ ret
+
+_qt_start:
+ movl (sp)+,r0 /* Get `only'. */
+ calls $3,(r0) /* Call `only'. */
+ calls $0,_qt_error /* `only' erroniously returned. */
+
+
+_qt_vstart:
+ movl (sp)+,r10 /* Get `pt'. */
+ movl (sp)+,r9 /* Get `startup'. */
+ movl (sp)+,r8 /* Get `vuserf'. */
+ movl (sp)+,r7 /* Get `cleanup'. */
+
+ pushl r10 /* Push `qt'. */
+ calls $1,(r9) /* Call `startup', pop `qt' on return. */
+
+ calls (sp)+,(r8) /* Call user's function. */
+
+ pushl r0 /* Push `vuserf_retval'. */
+ pushl r10 /* Push `qt'. */
+ calls $2,(r7) /* Call `cleanup', never return. */
+
+ calls $0,_qt_error /* `cleanup' erroniously returned. */
diff --git a/ext/systemc/src/sysc/qt/md/vax_b.s b/ext/systemc/src/sysc/qt/md/vax_b.s
new file mode 100644
index 000000000..2db2d4fec
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/md/vax_b.s
@@ -0,0 +1,92 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+ .text
+ .globl _b_call_reg
+ .globl _b_call_imm
+ .globl _b_add
+ .globl _b_load
+
+_b_null:
+ .word 0x0
+ ret
+
+_b_call_reg:
+ .word 0x0
+ movl 4(ap),r0
+ moval _b_null,r1
+L0:
+ calls $0,(r1)
+ calls $0,(r1)
+ calls $0,(r1)
+ calls $0,(r1)
+ calls $0,(r1)
+
+ subl2 $5,r0
+ bgtr L0
+ ret
+
+
+_b_call_imm:
+ .word 0x0
+ movl 4(ap),r0
+L1:
+ calls $0,_b_null
+ calls $0,_b_null
+ calls $0,_b_null
+ calls $0,_b_null
+ calls $0,_b_null
+
+ subl2 $5,r0
+ bgtr L1
+ ret
+
+
+_b_add:
+ .word 0x0
+ movl 4(ap),r0
+L2:
+ subl2 $1,r0
+ subl2 $1,r0
+ subl2 $1,r0
+ subl2 $1,r0
+ subl2 $1,r0
+
+ subl2 $1,r0
+ subl2 $1,r0
+ subl2 $1,r0
+ subl2 $1,r0
+ subl2 $1,r0
+
+ bgtr L2
+ ret
+
+
+_b_load:
+ .word 0x0
+ movl 4(ap),r0
+L3:
+ movl 0(sp),r1
+ movl 4(sp),r1
+ movl 8(sp),r1
+ movl 12(sp),r1
+ movl 16(sp),r1
+ movl 20(sp),r1
+ movl 24(sp),r1
+ movl 28(sp),r1
+ movl 32(sp),r1
+ movl 36(sp),r1
+
+ subl2 $1,r0
+ bgtr L3
+ ret
diff --git a/ext/systemc/src/sysc/qt/meas.c b/ext/systemc/src/sysc/qt/meas.c
new file mode 100644
index 000000000..3faab3c52
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/meas.c
@@ -0,0 +1,1049 @@
+/* meas.c -- measure qt stuff. */
+
+#include "copyright.h"
+
+/* Need this to get assertions under Mach on the Sequent/i386: */
+#ifdef __i386__
+#define assert(ex) \
+ do { \
+ if (!(ex)) { \
+ fprintf (stderr, "[%s:%d] Assertion " #ex " failed\n", __FILE__, __LINE__); \
+ abort(); \
+ } \
+ } while (0)
+#else
+#include <assert.h>
+#endif
+
+/* This really ought to be defined in some ANSI include file (*I*
+ think...), but it's defined here instead, which leads us to another
+ machine dependency.
+
+ The `iaddr_t' type is an integer representation of a pointer,
+ suited for doing arithmetic on addresses, e.g. to round an address
+ to an alignment boundary. */
+typedef unsigned long iaddr_t;
+
+#include <stdarg.h> /* For varargs tryout. */
+#include <stdio.h>
+#include "b.h"
+#include "qt.h"
+#include "stp.h"
+
+extern void exit (int status);
+extern int atoi (char const *s);
+extern int fprintf (FILE *out, char const *fmt, ...);
+extern int fputs (char const *s, FILE *fp);
+extern void free (void *sto);
+extern void *malloc (unsigned nbytes);
+extern void perror (char const *s);
+
+void usage (void);
+void tracer(void);
+
+/* Round `v' to be `a'-aligned, assuming `a' is a power of two. */
+#define ROUND(v, a) (((v) + (a) - 1) & ~((a)-1))
+
+typedef struct thread_t {
+ qt_t *qt; /* Pointer to thread of function... */
+ void *stk;
+ void *top; /* Set top of stack if reuse. */
+ struct thread_t *next;
+} thread_t;
+
+
+ static thread_t *
+t_alloc (void)
+{
+ thread_t *t;
+ int ssz = 0x1000;
+
+ t = malloc (sizeof(thread_t));
+ if (!t) {
+ perror ("malloc");
+ exit (1);
+ }
+ assert (ssz > QT_STKBASE);
+ t->stk = malloc (ssz);
+ t->stk = (void *)ROUND (((iaddr_t)t->stk), QT_STKALIGN);
+ if (!t->stk) {
+ perror ("malloc");
+ exit (1);
+ }
+ assert ((((iaddr_t)t->stk) & (QT_STKALIGN-1)) == 0);
+ t->top = QT_SP (t->stk, ssz - QT_STKBASE);
+
+ return (t);
+}
+
+
+ static thread_t *
+t_create (qt_only_t *starter, void *p0, qt_userf_t *f)
+{
+ thread_t *t;
+
+ t = t_alloc();
+ t->qt = QT_ARGS (t->top, p0, t, f, starter);
+ return (t);
+}
+
+
+ static void
+t_free (thread_t *t)
+{
+ free (t->stk);
+ free (t);
+}
+
+
+ static void *
+t_null (qt_t *old, void *p1, void *p2)
+{
+ /* return (garbage); */
+}
+
+
+ static void *
+t_splat (qt_t *old, void *oldp, void *null)
+{
+ *(qt_t **)oldp = old;
+ /* return (garbage); */
+}
+
+
+static char const test01_msg[] =
+ "*QT_SP(sto,sz), QT_ARGS(top,p0,p1,userf,first)";
+
+static char const *test01_descr[] = {
+ "Performs 1 QT_SP and one QT_ARGS per iteration.",
+ NULL
+};
+
+/* This test gives a guess on how long it takes to initalize
+ a thread. */
+
+ static void
+test01 (int n)
+{
+ char stack[QT_STKBASE+QT_STKALIGN];
+ char *stk;
+ qt_t *top;
+
+ stk = (char *)ROUND (((iaddr_t)stack), QT_STKALIGN);
+
+ {
+ int i;
+
+ for (i=0; i<QT_STKBASE; ++i) {
+ stk[i] = 0;
+ }
+ }
+
+ while (n>0) {
+ /* RETVALUSED */
+ top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0);
+#ifdef NDEF
+ top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0);
+ top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0);
+ top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0);
+ top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0);
+
+ top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0);
+ top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0);
+ top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0);
+ top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0);
+ top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0);
+
+ n -= 10;
+#else
+ n -= 1;
+#endif
+ }
+}
+
+
+static char const test02_msg[] = "QT_BLOCKI (0, 0, test02_aux, t->qt)";
+static qt_t *rootthread;
+
+ static void
+test02_aux1 (void *pu, void *pt, qt_userf_t *f)
+{
+ QT_ABORT (t_null, 0, 0, rootthread);
+}
+
+ static void *
+test02_aux2 (qt_t *old, void *farg1, void *farg2)
+{
+ rootthread = old;
+ /* return (garbage); */
+}
+
+ static void
+test02 (int n)
+{
+ thread_t *t;
+
+ while (n>0) {
+ t = t_create (test02_aux1, 0, 0);
+ QT_BLOCKI (test02_aux2, 0, 0, t->qt);
+ t_free (t);
+ t = t_create (test02_aux1, 0, 0);
+ QT_BLOCKI (test02_aux2, 0, 0, t->qt);
+ t_free (t);
+ t = t_create (test02_aux1, 0, 0);
+ QT_BLOCKI (test02_aux2, 0, 0, t->qt);
+ t_free (t);
+ t = t_create (test02_aux1, 0, 0);
+ QT_BLOCKI (test02_aux2, 0, 0, t->qt);
+ t_free (t);
+ t = t_create (test02_aux1, 0, 0);
+ QT_BLOCKI (test02_aux2, 0, 0, t->qt);
+ t_free (t);
+
+ n -= 5;
+ }
+}
+
+
+static char const test03_msg[] = "QT_BLOCKI (...) test vals are right.";
+
+
+/* Called by the thread function when it wants to shut down.
+ Return a value to the main thread. */
+
+ static void *
+test03_aux0 (qt_t *old_is_garbage, void *farg1, void *farg2)
+{
+ assert (farg1 == (void *)5);
+ assert (farg2 == (void *)6);
+ return ((void *)15); /* Some unlikely value. */
+}
+
+
+/* Called during new thread startup by main thread. Since the new
+ thread has never run before, return value is ignored. */
+
+ static void *
+test03_aux1 (qt_t *old, void *farg1, void *farg2)
+{
+ assert (old != NULL);
+ assert (farg1 == (void *)5);
+ assert (farg2 == (void *)6);
+ rootthread = old;
+ return ((void *)16); /* Different than `15'. */
+}
+
+ static void
+test03_aux2 (void *pu, void *pt, qt_userf_t *f)
+{
+ assert (pu == (void *)1);
+ assert (f == (qt_userf_t *)4);
+ QT_ABORT (test03_aux0, (void *)5, (void *)6, rootthread);
+}
+
+ static void
+test03 (int n)
+{
+ thread_t *t;
+ void *rv;
+
+ while (n>0) {
+ t = t_create (test03_aux2, (void *)1, (qt_userf_t *)4);
+ rv = QT_BLOCKI (test03_aux1, (void *)5, (void *)6, t->qt);
+ assert (rv == (void *)15);
+ t_free (t);
+
+ --n;
+ }
+}
+
+
+static char const test04_msg[] = "stp_start w/ no threads.";
+
+ static void
+test04 (int n)
+{
+ while (n>0) {
+ stp_init(); stp_start();
+ stp_init(); stp_start();
+ stp_init(); stp_start();
+ stp_init(); stp_start();
+ stp_init(); stp_start();
+
+ stp_init(); stp_start();
+ stp_init(); stp_start();
+ stp_init(); stp_start();
+ stp_init(); stp_start();
+ stp_init(); stp_start();
+
+ n -= 10;
+ }
+}
+
+
+static char const test05_msg[] = "stp w/ 2 yielding thread.";
+
+ static void
+test05_aux (void *null)
+{
+ stp_yield();
+ stp_yield();
+}
+
+ static void
+test05 (int n)
+{
+ while (n>0) {
+ stp_init();
+ stp_create (test05_aux, 0);
+ stp_create (test05_aux, 0);
+ stp_start();
+
+ --n;
+ }
+}
+
+
+static char const test06_msg[] = "*QT_ARGS(...), QT_BLOCKI one thread";
+
+static char const *test06_descr[] = {
+ "Does a QT_ARGS, QT_BLOCKI to a helper function that saves the",
+ "stack pointer of the main thread, calls an `only' function that",
+ "saves aborts the thread, calling a null helper function.",
+ ":: start/stop = QT_ARGS + QT_BLOCKI + QT_ABORT + 3 procedure calls.",
+ NULL
+};
+
+/* This test initializes a thread, runs it, then returns to the main
+ program, which reinitializes the thread, runs it again, etc. Each
+ iteration corresponds to 1 init, 1 abort, 1 block. */
+
+static qt_t *test06_sp;
+
+
+ static void
+test06_aux2 (void *null0a, void *null1b, void *null2b, qt_userf_t *null)
+{
+ QT_ABORT (t_null, 0, 0, test06_sp);
+}
+
+
+ static void *
+test06_aux3 (qt_t *sp, void *null0c, void *null1c)
+{
+ test06_sp = sp;
+ /* return (garbage); */
+}
+
+
+ static void
+test06 (int n)
+{
+ thread_t *t;
+
+ t = t_create (0, 0, 0);
+
+ while (n>0) {
+ /* RETVALUSED */
+ QT_ARGS (t->top, 0, 0, 0, test06_aux2);
+ QT_BLOCKI (test06_aux3, 0, 0, t->qt);
+#ifdef NDEF
+ /* RETVALUSED */
+ QT_ARGS (t->top, 0, 0, 0, test06_aux2);
+ QT_BLOCKI (test06_aux3, 0, 0, t->qt);
+
+ /* RETVALUSED */
+ QT_ARGS (t->top, 0, 0, 0, test06_aux2);
+ QT_BLOCKI (test06_aux3, 0, 0, t->qt);
+
+ /* RETVALUSED */
+ QT_ARGS (t->top, 0, 0, 0, test06_aux2);
+ QT_BLOCKI (test06_aux3, 0, 0, t->qt);
+
+ /* RETVALUSED */
+ QT_ARGS (t->top, 0, 0, 0, test06_aux2);
+ QT_BLOCKI (test06_aux3, 0, 0, t->qt);
+
+ n -= 5;
+#else
+ --n;
+#endif
+ }
+}
+
+static char test07_msg[] = "*cswap between threads";
+
+static char const *test07_descr[] = {
+ "Build a chain of threads where each thread has a fixed successor.",
+ "There is no scheduling performed. Each thread but one is a loop",
+ "that simply blocks with QT_BLOCKI, calling a helper that saves the",
+ "current stack pointer. The last thread decrements a count, and,",
+ "if zero, aborts back to the main thread. Else it continues with",
+ "the blocking chain. The count is divided by the number of threads",
+ "in the chain, so `n' is the number of integer block operations.",
+ ":: integer cswap = QT_BLOCKI + a procedure call.",
+ NULL
+};
+
+/* This test repeatedly blocks a bunch of threads.
+ Each iteration corresponds to one block operation.
+
+ The threads are arranged so that there are TEST07_N-1 of them that
+ run `test07_aux2'. Each one of those blocks saving it's sp to
+ storage owned by the preceding thread; a pointer to that storage is
+ passed in via `mep'. Each thread has a handle on it's own storage
+ for the next thread, referenced by `nxtp', and it blocks by passing
+ control to `*nxtp', telling the helper function to save its state
+ in `*mep'. The last thread in the chain decrements a count and, if
+ it's gone below zero, returns to `test07'; otherwise, it invokes
+ the first thread in the chain. */
+
+static qt_t *test07_heavy;
+
+#define TEST07_N (4)
+
+
+ static void
+test07_aux2 (void *null0, void *mep, void *nxtp, qt_userf_t *null)
+{
+ qt_t *nxt;
+
+ while (1) {
+ nxt = *(qt_t **)nxtp;
+#ifdef NDEF
+ printf ("Helper 0x%p\n", nxtp);
+#endif
+ QT_BLOCKI (t_splat, mep, 0, nxt);
+ }
+}
+
+ static void
+test07_aux3 (void *np, void *mep, void *nxtp, qt_userf_t *null)
+{
+ int n;
+
+ n = *(int *)np;
+ while (1) {
+ n -= TEST07_N;
+ if (n<0) {
+ QT_ABORT (t_splat, mep, 0, test07_heavy);
+ }
+ QT_BLOCKI (t_splat, mep, 0, *(qt_t **)nxtp);
+ }
+}
+
+
+ static void
+test07 (int n)
+{
+ int i;
+ thread_t *t[TEST07_N];
+
+ for (i=0; i<TEST07_N; ++i) {
+ t[i] = t_create (0, 0, 0);
+ }
+ for (i=0; i<TEST07_N-1; ++i) {
+ /* RETVALUSED */
+ QT_ARGS (t[i]->top, 0, &t[i]->qt, &t[i+1]->qt, test07_aux2);
+ }
+ /* RETVALUSED */
+ QT_ARGS (t[i]->top, &n, &t[TEST07_N-1]->qt, &t[0]->qt, test07_aux3);
+ QT_BLOCKI (t_splat, &test07_heavy, 0, t[0]->qt);
+}
+
+
+static char test08_msg[] = "Floating-point cswap between threads";
+
+static char const *test08_descr[] = {
+ "Measure context switch times including floating-point, use QT_BLOCK.",
+ NULL
+};
+
+static qt_t *test08_heavy;
+
+#define TEST08_N (4)
+
+
+ static void
+test08_aux2 (void *null0, void *mep, void *nxtp, qt_userf_t *null)
+{
+ qt_t *nxt;
+
+ while (1) {
+ nxt = *(qt_t **)nxtp;
+ QT_BLOCK (t_splat, mep, 0, nxt);
+ }
+}
+
+ static void
+test08_aux3 (void *np, void *mep, void *nxtp, qt_userf_t *null)
+{
+ int n;
+
+ n = *(int *)np;
+ while (1) {
+ n -= TEST08_N;
+ if (n<0) {
+ QT_ABORT (t_splat, mep, 0, test08_heavy);
+ }
+ QT_BLOCK (t_splat, mep, 0, *(qt_t **)nxtp);
+ }
+}
+
+
+ static void
+test08 (int n)
+{
+ int i;
+ thread_t *t[TEST08_N];
+
+ for (i=0; i<TEST08_N; ++i) {
+ t[i] = t_create (0, 0, 0);
+ }
+ for (i=0; i<TEST08_N-1; ++i) {
+ /* RETVALUSED */
+ QT_ARGS (t[i]->top, 0, &t[i]->qt, &t[i+1]->qt, test08_aux2);
+ }
+ /* RETVALUSED */
+ QT_ARGS (t[i]->top, &n, &t[TEST08_N-1]->qt, &t[0]->qt, test08_aux3);
+ QT_BLOCK (t_splat, &test08_heavy, 0, t[0]->qt);
+}
+
+
+/* Test the varargs procedure calling. */
+
+char const test09_msg[] = { "Start and run threads using varargs." };
+
+thread_t *test09_t0, *test09_t1, *test09_t2, *test09_main;
+
+ thread_t *
+test09_create (qt_startup_t *start, qt_vuserf_t *f,
+ qt_cleanup_t *cleanup, int nbytes, ...)
+{
+ va_list ap;
+ thread_t *t;
+
+ t = t_alloc();
+ va_start (ap, nbytes);
+ t->qt = QT_VARGS (t->top, nbytes, ap, t, start, f, cleanup);
+ va_end (ap);
+ return (t);
+}
+
+
+ static void
+test09_cleanup (void *pt, void *vuserf_retval)
+{
+ assert (vuserf_retval == (void *)17);
+ QT_ABORT (t_splat, &((thread_t *)pt)->qt, 0,
+ ((thread_t *)pt)->next->qt);
+}
+
+
+ static void
+test09_start (void *pt)
+{
+}
+
+
+ static void *
+test09_user0 (void)
+{
+ QT_BLOCKI (t_splat, &test09_t0->qt, 0, test09_t1->qt);
+ return ((void *)17);
+}
+
+ static void *
+test09_user2 (int one, int two)
+{
+ assert (one == 1);
+ assert (two == 2);
+ QT_BLOCKI (t_splat, &test09_t1->qt, 0, test09_t2->qt);
+ assert (one == 1);
+ assert (two == 2);
+ return ((void *)17);
+}
+
+ static void *
+test09_user10 (int one, int two, int three, int four, int five,
+ int six, int seven, int eight, int nine, int ten)
+{
+ assert (one == 1);
+ assert (two == 2);
+ assert (three == 3);
+ assert (four == 4);
+ assert (five == 5);
+ assert (six == 6);
+ assert (seven == 7);
+ assert (eight == 8);
+ assert (nine == 9);
+ assert (ten == 10);
+ QT_BLOCKI (t_splat, &test09_t2->qt, 0, test09_main->qt);
+ assert (one == 1);
+ assert (two == 2);
+ assert (three == 3);
+ assert (four == 4);
+ assert (five == 5);
+ assert (six == 6);
+ assert (seven == 7);
+ assert (eight == 8);
+ assert (nine == 9);
+ assert (ten == 10);
+ return ((void *)17);
+}
+
+
+ void
+test09 (int n)
+{
+ thread_t main;
+
+ test09_main = &main;
+
+ while (--n >= 0) {
+ test09_t0 = test09_create (test09_start, (qt_vuserf_t*)test09_user0,
+ test09_cleanup, 0);
+ test09_t1 = test09_create (test09_start, (qt_vuserf_t*)test09_user2,
+ test09_cleanup, 2 * sizeof(qt_word_t), 1, 2);
+ test09_t2 = test09_create (test09_start, (qt_vuserf_t*)test09_user10,
+ test09_cleanup, 10 * sizeof(qt_word_t),
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+
+ /* Chaining used by `test09_cleanup' to determine who is next. */
+ test09_t0->next = test09_t1;
+ test09_t1->next = test09_t2;
+ test09_t2->next = test09_main;
+
+ QT_BLOCKI (t_splat, &test09_main->qt, 0, test09_t0->qt);
+ QT_BLOCKI (t_splat, &test09_main->qt, 0, test09_t0->qt);
+
+ t_free (test09_t0);
+ t_free (test09_t1);
+ t_free (test09_t2);
+ }
+}
+
+
+ /* Test 10/11/12: time the cost of various number of args. */
+
+char const test10_msg[] = { "*Test varargs init & startup w/ 0 args." };
+
+char const *test10_descr[] = {
+ "Start and stop threads that use variant argument lists (varargs).",
+ "Each thread is initialized by calling a routine that calls",
+ "QT_VARARGS. Then runs the thread by calling QT_BLOCKI to hald the",
+ "main thread, a helper that saves the main thread's stack pointer,",
+ "a null startup function, a null user function, a cleanup function",
+ "that calls QT_ABORT and restarts the main thread. Copies no user",
+ "parameters.",
+ ":: varargs start/stop = QT_BLOCKI + QT_ABORT + 6 function calls.",
+ NULL
+};
+
+/* Helper function to send control back to main.
+ Don't save anything. */
+
+
+/* Helper function for starting the varargs thread. Save the stack
+ pointer of the main thread so we can get back there eventually. */
+
+
+/* Startup function for a varargs thread. */
+
+ static void
+test10_startup (void *pt)
+{
+}
+
+
+/* User function for a varargs thread. */
+
+ static void *
+test10_run (int arg0, ...)
+{
+ /* return (garbage); */
+}
+
+
+/* Cleanup function for a varargs thread. Send control
+ back to the main thread. Don't save any state from the thread that
+ is halting. */
+
+ void
+test10_cleanup (void *pt, void *vuserf_retval)
+{
+ QT_ABORT (t_null, 0, 0, ((thread_t *)pt)->qt);
+}
+
+
+ void
+test10_init (thread_t *new, thread_t *next, int nbytes, ...)
+{
+ va_list ap;
+
+ va_start (ap, nbytes);
+ new->qt = QT_VARGS (new->top, nbytes, ap, next, test10_startup,
+ test10_run, test10_cleanup);
+ va_end (ap);
+}
+
+
+ void
+test10 (int n)
+{
+ thread_t main;
+ thread_t *t;
+
+ t = t_alloc();
+ t->next = &main;
+
+ while (--n >= 0) {
+ test10_init (t, &main, 0);
+ QT_BLOCKI (t_splat, &main.qt, 0, t->qt);
+ }
+ t_free (t);
+}
+
+
+char const test11_msg[] = { "*Test varargs init & startup w/ 2 args." };
+
+char const *test11_descr[] = {
+ "Varargs initialization/run. Copies 2 user arguments.",
+ ":: varargs 2 start/stop = QT_VARGS(2 args), QT_BLOCKI, QT_ABORT, 6 f() calls.",
+ NULL
+};
+
+
+ void
+test11 (int n)
+{
+ thread_t main;
+ thread_t *t;
+
+ t = t_alloc();
+ t->next = &main;
+
+ while (--n >= 0) {
+ test10_init (t, &main, 2 * sizeof(int), 2, 1);
+ QT_BLOCKI (t_splat, &main.qt, 0, t->qt);
+ }
+ t_free (t);
+}
+
+char const test12_msg[] = { "*Test varargs init & startup w/ 4 args." };
+
+char const *test12_descr[] = {
+ "Varargs initialization/run. Copies 4 user arguments.",
+ ":: varargs 4 start/stop = QT_VARGS(4 args), QT_BLOCKI, QT_ABORT, 6 f() calls.",
+ NULL
+};
+
+
+ void
+test12 (int n)
+{
+ thread_t main;
+ thread_t *t;
+
+ t = t_alloc();
+ t->next = &main;
+
+ while (--n >= 0) {
+ test10_init (t, &main, 4 * sizeof(int), 4, 3, 2, 1);
+ QT_BLOCKI (t_splat, &main.qt, 0, t->qt);
+ }
+ t_free (t);
+}
+
+
+char const test13_msg[] = { "*Test varargs init & startup w/ 8 args." };
+
+char const *test13_descr[] = {
+ "Varargs initialization/run. Copies 8 user arguments.",
+ ":: varargs 8 start/stop = QT_VARGS(8 args), QT_BLOCKI, QT_ABORT, 6 f() calls.",
+ NULL
+};
+
+ void
+test13 (int n)
+{
+ thread_t main;
+ thread_t *t;
+
+ t = t_alloc();
+ t->next = &main;
+
+ while (--n >= 0) {
+ test10_init (t, &main, 8 * sizeof(int), 8, 7, 6, 5, 4, 3, 2, 1);
+ QT_BLOCKI (t_splat, &main.qt, 0, t->qt);
+ }
+ t_free (t);
+}
+
+
+char const test14_msg[] = { "*Test varargs initialization w/ 0 args." };
+
+char const *test14_descr[] = {
+ "Varargs initialization without running the thread. Just calls",
+ "QT_VARGS.",
+ ":: varargs 0 init = QT_VARGS()",
+ NULL
+};
+
+ void
+test14 (int n)
+{
+ thread_t main;
+ thread_t *t;
+
+ t = t_alloc();
+ t->next = &main;
+
+ while (--n >= 0) {
+ test10_init (t, &main, 0 * sizeof(int));
+ }
+ t_free (t);
+}
+
+
+char const test15_msg[] = { "*Test varargs initialization w/ 2 args." };
+
+char const *test15_descr[] = {
+ "Varargs initialization without running the thread. Just calls",
+ "QT_VARGS.",
+ ":: varargs 2 init = QT_VARGS(2 args)",
+ NULL
+};
+
+ void
+test15 (int n)
+{
+ thread_t main;
+ thread_t *t;
+
+ t = t_alloc();
+ t->next = &main;
+
+ while (--n >= 0) {
+ test10_init (t, &main, 2 * sizeof(int), 2, 1);
+ }
+ t_free (t);
+}
+
+char const test16_msg[] = { "*Test varargs initialization w/ 4 args." };
+
+char const *test16_descr[] = {
+ "Varargs initialization without running the thread. Just calls",
+ "QT_VARGS.",
+ ":: varargs 4 init = QT_VARGS(4 args)",
+ NULL
+};
+
+
+ void
+test16 (int n)
+{
+ thread_t main;
+ thread_t *t;
+
+ t = t_alloc();
+ t->next = &main;
+
+ while (--n >= 0) {
+ test10_init (t, &main, 4 * sizeof(int), 4, 3, 2, 1);
+ }
+ t_free (t);
+}
+
+
+char const test17_msg[] = { "*Test varargs initialization w/ 8 args." };
+
+char const *test17_descr[] = {
+ "Varargs initialization without running the thread. Just calls",
+ "QT_VARGS.",
+ ":: varargs 8 init = QT_VARGS(8 args)",
+ NULL
+};
+
+
+ void
+test17 (int n)
+{
+ thread_t main;
+ thread_t *t;
+
+ t = t_alloc();
+ t->next = &main;
+
+ while (--n >= 0) {
+ test10_init (t, &main, 8 * sizeof(int), 8, 7, 6, 5, 4, 3, 2, 1);
+ }
+ t_free (t);
+}
+
+ /* Test times for basic machine operations. */
+
+char const test18_msg[] = { "*Call register indirect." };
+char const *test18_descr[] = { NULL };
+
+ void
+test18 (int n)
+{
+ b_call_reg (n);
+}
+
+
+char const test19_msg[] = { "*Call immediate." };
+char const *test19_descr[] = { NULL };
+
+ void
+test19 (int n)
+{
+ b_call_imm (n);
+}
+
+
+char const test20_msg[] = { "*Add register-to-register." };
+char const *test20_descr[] = { NULL };
+
+ void
+test20 (int n)
+{
+ b_add (n);
+}
+
+
+char const test21_msg[] = { "*Load memory to a register." };
+char const *test21_descr[] = { NULL };
+
+ void
+test21 (int n)
+{
+ b_load (n);
+}
+
+ /* Driver. */
+
+typedef struct foo_t {
+ char const *msg; /* Message to print for generic help. */
+ char const **descr; /* A description of what is done by the test. */
+ void (*f)(int n);
+} foo_t;
+
+
+static foo_t foo[] = {
+ { "Usage:\n", NULL, (void(*)(int n))usage },
+ { test01_msg, test01_descr, test01 },
+ { test02_msg, NULL, test02 },
+ { test03_msg, NULL, test03 },
+ { test04_msg, NULL, test04 },
+ { test05_msg, NULL, test05 },
+ { test06_msg, test06_descr, test06 },
+ { test07_msg, test07_descr, test07 },
+ { test08_msg, test08_descr, test08 },
+ { test09_msg, NULL, test09 },
+ { test10_msg, test10_descr, test10 },
+ { test11_msg, test11_descr, test11 },
+ { test12_msg, test12_descr, test12 },
+ { test13_msg, test13_descr, test13 },
+ { test14_msg, test14_descr, test14 },
+ { test15_msg, test15_descr, test15 },
+ { test16_msg, test16_descr, test16 },
+ { test17_msg, test17_descr, test17 },
+ { test18_msg, test18_descr, test18 },
+ { test19_msg, test19_descr, test19 },
+ { test20_msg, test20_descr, test20 },
+ { test21_msg, test21_descr, test21 },
+ { 0, 0 }
+};
+
+static int tv = 0;
+
+ void
+tracer ()
+{
+
+ fprintf (stderr, "tracer\t%d\n", tv++);
+ fflush (stderr);
+}
+
+ void
+tracer2 (void *val)
+{
+ fprintf (stderr, "tracer2\t%d val=0x%p", tv++, val);
+ fflush (stderr);
+}
+
+
+ void
+describe()
+{
+ int i;
+ FILE *out = stdout;
+
+ for (i=0; foo[i].msg; ++i) {
+ if (foo[i].descr) {
+ int j;
+
+ putc ('\n', out);
+ fprintf (out, "[%d]\n", i);
+ for (j=0; foo[i].descr[j]; ++j) {
+ fputs (foo[i].descr[j], out);
+ putc ('\n', out);
+ }
+ }
+ }
+ exit (0);
+}
+
+
+ void
+usage()
+{
+ int i;
+
+ fputs (foo[0].msg, stderr);
+ for (i=1; foo[i].msg; ++i) {
+ fprintf (stderr, "%2d\t%s\n", i, foo[i].msg);
+ }
+ exit (1);
+}
+
+
+ void
+args (int *which, int *n, int argc, char **argv)
+{
+ static int nfuncs = 0;
+
+ if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h') {
+ describe();
+ }
+
+ if (nfuncs == 0) {
+ for (nfuncs=0; foo[nfuncs].msg; ++nfuncs)
+ ;
+ }
+
+ if (argc != 2 && argc != 3) {
+ usage();
+ }
+
+ *which = atoi (argv[1]);
+ if (*which < 0 || *which >= nfuncs) {
+ usage();
+ }
+ *n = (argc == 3)
+ ? atoi (argv[2])
+ : 1;
+}
+
+
+ int
+main (int argc, char **argv)
+{
+ int which, n;
+ args (&which, &n, argc, argv);
+ (*(foo[which].f))(n);
+ exit (0);
+ return (0);
+}
diff --git a/ext/systemc/src/sysc/qt/qt.c b/ext/systemc/src/sysc/qt/qt.c
new file mode 100644
index 000000000..204d38397
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/qt.c
@@ -0,0 +1,56 @@
+#include "copyright.h"
+#include "qt.h"
+
+// static void *qt_sp_bottom_save;
+
+#ifdef QT_VARGS_DEFAULT
+
+/* If the stack grows down, `vargs' is a pointer to the lowest
+ address in the block of arguments. If the stack grows up, it is a
+ pointer to the highest address in the block. */
+
+ qt_t *
+qt_vargs (qt_t *sp, int nbytes, void *vargs,
+ void *pt, qt_startup_t *startup,
+ qt_vuserf_t *vuserf, qt_cleanup_t *cleanup)
+{
+ int i;
+
+ sp = QT_VARGS_MD0 (sp, nbytes);
+#ifdef QT_GROW_UP
+ for (i=nbytes/sizeof(qt_word_t); i>0; --i) {
+ QT_SPUT (QT_VARGS_ADJUST(sp), i, ((qt_word_t *)vargs)[-i]);
+ }
+#else
+ for (i=nbytes/sizeof(qt_word_t); i>0; --i) {
+ QT_SPUT (QT_VARGS_ADJUST(sp), i-1, ((qt_word_t *)vargs)[i-1]);
+ }
+#endif
+
+ QT_VARGS_MD1 (QT_VADJ(sp));
+ QT_SPUT (QT_VADJ(sp), QT_VARGT_INDEX, pt);
+ QT_SPUT (QT_VADJ(sp), QT_VSTARTUP_INDEX, startup);
+ QT_SPUT (QT_VADJ(sp), QT_VUSERF_INDEX, vuserf);
+ QT_SPUT (QT_VADJ(sp), QT_VCLEANUP_INDEX, cleanup);
+ return ((qt_t *)QT_VADJ(sp));
+}
+#endif /* def QT_VARGS_DEFAULT */
+
+#ifdef __cplusplus
+extern "C"
+#endif
+ void
+qt_null (void)
+{
+}
+
+#ifdef __cplusplus
+extern "C"
+#endif
+ void
+qt_error (void)
+{
+ extern void abort(void);
+
+ abort();
+}
diff --git a/ext/systemc/src/sysc/qt/qt.h b/ext/systemc/src/sysc/qt/qt.h
new file mode 100644
index 000000000..40a9f531b
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/qt.h
@@ -0,0 +1,192 @@
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+#ifndef QUICKTHREADS_QT_H
+#define QUICKTHREADS_QT_H
+
+#if !defined(SC_USE_PTHREADS)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sysc/qt/qtmd.h>
+
+
+/* A QuickThreads thread is represented by it's current stack pointer.
+ To restart a thread, you merely need pass the current sp (qt_t*) to
+ a QuickThreads primitive. `qt_t*' is a location on the stack. To
+ improve type checking, represent it by a particular struct. */
+
+typedef struct qt_t {
+ char dummy;
+} qt_t;
+
+
+/* Alignment is guaranteed to be a power of two. */
+#ifndef QUICKTHREADS_STKALIGN
+ #error "Need to know the machine-dependent stack alignment."
+#endif
+
+#define QUICKTHREADS_STKROUNDUP(bytes) \
+ (((bytes)+QUICKTHREADS_STKALIGN) & ~(QUICKTHREADS_STKALIGN-1))
+
+
+/* Find ``top'' of the stack, space on the stack. */
+#ifndef QUICKTHREADS_SP
+#ifdef QUICKTHREADS_GROW_DOWN
+#define QUICKTHREADS_SP(sto, size) ((qt_t *)(&((char *)(sto))[(size)]))
+#endif
+#ifdef QUICKTHREADS_GROW_UP
+#define QUICKTHREADS_SP(sto, size) ((qt_t *)(sto))
+#endif
+#if !defined(QUICKTHREADS_SP)
+ #error "QUICKTHREADS_QT_H: Stack must grow up or down!"
+#endif
+#endif
+
+
+/* The type of the user function:
+ For non-varargs, takes one void* function.
+ For varargs, takes some number of arguments. */
+typedef void *(qt_userf_t)(void *pu);
+typedef void *(qt_vuserf_t)(int arg0, ...);
+
+/* For non-varargs, just call a client-supplied function,
+ it does all startup and cleanup, and also calls the user's
+ function. */
+typedef void (qt_only_t)(void *pu, void *pt, qt_userf_t *userf);
+
+/* For varargs, call `startup', then call the user's function,
+ then call `cleanup'. */
+typedef void (qt_startup_t)(void *pt);
+typedef void (qt_cleanup_t)(void *pt, void *vuserf_return);
+
+
+/* Internal helper for putting stuff on stack. */
+#ifndef QUICKTHREADS_SPUT
+#define QUICKTHREADS_SPUT(top, at, val) \
+ (((qt_word_t *)(top))[(at)] = (qt_word_t)(val))
+#endif
+
+
+/* Push arguments for the non-varargs case. */
+#ifndef QUICKTHREADS_ARGS
+
+#ifndef QUICKTHREADS_ARGS_MD
+#define QUICKTHREADS_ARGS_MD (0)
+#endif
+
+#ifndef QUICKTHREADS_STKBASE
+ #error "Need to know the machine-dependent stack allocation."
+#endif
+
+/* All things are put on the stack relative to the final value of
+ the stack pointer. */
+#ifdef QUICKTHREADS_GROW_DOWN
+#define QUICKTHREADS_ADJ(sp) (((char *)sp) - QUICKTHREADS_STKBASE)
+#else
+#define QUICKTHREADS_ADJ(sp) (((char *)sp) + QUICKTHREADS_STKBASE)
+#endif
+
+#define QUICKTHREADS_ARGS(sp, pu, pt, userf, only) \
+ (QUICKTHREADS_ARGS_MD (QUICKTHREADS_ADJ(sp)), \
+ QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ONLY_INDEX, only), \
+ QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_USER_INDEX, userf), \
+ QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ARGT_INDEX, pt), \
+ QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ARGU_INDEX, pu), \
+ ((qt_t *)QUICKTHREADS_ADJ(sp)))
+
+#endif
+
+
+/* Push arguments for the varargs case.
+ Has to be a function call because initialization is an expression
+ and we need to loop to copy nbytes of stuff on to the stack.
+ But that's probably OK, it's not terribly cheap, anyway. */
+
+#ifdef QUICKTHREADS_VARGS_DEFAULT
+#ifndef QUICKTHREADS_VARGS_MD0
+#define QUICKTHREADS_VARGS_MD0(sp, vasize) (sp)
+#endif
+#ifndef QUICKTHREADS_VARGS_MD1
+#define QUICKTHREADS_VARGS_MD1(sp) do { ; } while (0)
+#endif
+
+#ifndef QUICKTHREADS_VSTKBASE
+ #error "Need base stack size for varargs functions."
+#endif
+
+/* Sometimes the stack pointer needs to munged a bit when storing
+ the list of arguments. */
+#ifndef QUICKTHREADS_VARGS_ADJUST
+#define QUICKTHREADS_VARGS_ADJUST(sp) (sp)
+#endif
+
+/* All things are put on the stack relative to the final value of
+ the stack pointer. */
+#ifdef QUICKTHREADS_GROW_DOWN
+#define QUICKTHREADS_VADJ(sp) (((char *)sp) - QUICKTHREADS_VSTKBASE)
+#else
+#define QUICKTHREADS_VADJ(sp) (((char *)sp) + QUICKTHREADS_VSTKBASE)
+#endif
+
+extern qt_t *qt_vargs (qt_t *sp, int nbytes, void *vargs,
+ void *pt, qt_startup_t *startup,
+ qt_vuserf_t *vuserf, qt_cleanup_t *cleanup);
+
+#ifndef QUICKTHREADS_VARGS
+#define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \
+ (qt_vargs (sp, nbytes, vargs, pt, startup, vuserf, cleanup))
+#endif
+
+#endif
+
+
+/* Save the state of the thread and call the helper function
+ using the stack of the new thread. */
+typedef void *(qt_helper_t)(qt_t *old, void *a0, void *a1);
+typedef void *(qt_block_t)(qt_helper_t *helper, void *a0, void *a1,
+ qt_t *newthread);
+
+/* Rearrange the parameters so that things passed to the helper
+ function are already in the right argument registers. */
+#ifndef QUICKTHREADS_ABORT
+extern void *qt_abort (qt_helper_t *h, void *a0, void *a1, qt_t *newthread);
+/* The following does, technically, `return' a value, but the
+ user had better not rely on it, since the function never
+ returns. */
+#define QUICKTHREADS_ABORT(h, a0, a1, newthread) \
+ do { qt_abort (h, a0, a1, newthread); } while (0)
+#endif
+
+#ifndef QUICKTHREADS_BLOCK
+extern void *qt_block (qt_helper_t *h, void *a0, void *a1,
+ qt_t *newthread);
+#define QUICKTHREADS_BLOCK(h, a0, a1, newthread) \
+ (qt_block (h, a0, a1, newthread))
+#endif
+
+#ifndef QUICKTHREADS_BLOCKI
+extern void *qt_blocki (qt_helper_t *h, void *a0, void *a1,
+ qt_t *newthread);
+#define QUICKTHREADS_BLOCKI(h, a0, a1, newthread) \
+ (qt_blocki (h, a0, a1, newthread))
+#endif
+
+#ifdef __cplusplus
+} /* Match `extern "C" {' at top. */
+#endif
+
+#endif // !defined(SC_USE_PTHREADS)
+#endif /* ndef QUICKTHREADS_H */
diff --git a/ext/systemc/src/sysc/qt/qtmd.h b/ext/systemc/src/sysc/qt/qtmd.h
new file mode 100644
index 000000000..f33203815
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/qtmd.h
@@ -0,0 +1,13 @@
+#if defined( __sparc ) || defined( __sparc__ )
+#include "sysc/qt/md/sparc.h"
+#elif defined( __hppa )
+#include "sysc/qt/md/hppa.h"
+#elif defined( __x86_64__ )
+#include "sysc/qt/md/iX86_64.h"
+#elif defined( __i386 )
+#include "sysc/qt/md/i386.h"
+#elif defined( __ppc__ )
+#include "sysc/qt/md/powerpc_mach.h"
+#elif defined( __powerpc )
+#include "sysc/qt/md/powerpc_sys5.h"
+#endif
diff --git a/ext/systemc/src/sysc/qt/stp.c b/ext/systemc/src/sysc/qt/stp.c
new file mode 100644
index 000000000..bfacc893b
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/stp.c
@@ -0,0 +1,199 @@
+#include "copyright.h"
+#include "qt.h"
+#include "stp.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define STP_STKSIZE (0x1000)
+
+/* `alignment' must be a power of 2. */
+#define STP_STKALIGN(sp, alignment) \
+ ((void *)((((qt_word_t)(sp)) + (alignment) - 1) & ~((alignment)-1)))
+
+
+/* The notion of a thread is merged with the notion of a queue.
+ Thread stuff: thread status (sp) and stuff to use during
+ (re)initialization. Queue stuff: next thread in the queue
+ (next). */
+
+struct stp_t {
+ qt_t *sp; /* QuickThreads handle. */
+ void *sto; /* `malloc'-allocated stack. */
+ struct stp_t *next; /* Next thread in the queue. */
+};
+
+
+/* A queue is a circular list of threads. The queue head is a
+ designated list element. If this is a uniprocessor-only
+ implementation we can store the `main' thread in this, but in a
+ multiprocessor there are several `heavy' threads but only one run
+ queue. A fancier implementation might have private run queues,
+ which would lead to a simpler (trivial) implementation */
+
+typedef struct stp_q_t {
+ stp_t t;
+ stp_t *tail;
+} stp_q_t;
+
+
+ /* Helper functions. */
+
+extern void *malloc (unsigned size);
+extern void perror (char const *msg);
+extern void free (void *sto);
+
+ void *
+xmalloc (unsigned size)
+{
+ void *sto;
+
+ sto = malloc (size);
+ if (!sto) {
+ perror ("malloc");
+ exit (1);
+ }
+ return (sto);
+}
+
+ /* Queue access functions. */
+
+ static void
+stp_qinit (stp_q_t *q)
+{
+ q->t.next = q->tail = &q->t;
+}
+
+
+ static stp_t *
+stp_qget (stp_q_t *q)
+{
+ stp_t *t;
+
+ t = q->t.next;
+ q->t.next = t->next;
+ if (t->next == &q->t) {
+ if (t == &q->t) { /* If it was already empty .. */
+ return (NULL); /* .. say so. */
+ }
+ q->tail = &q->t; /* Else now it is empty. */
+ }
+ return (t);
+}
+
+
+ static void
+stp_qput (stp_q_t *q, stp_t *t)
+{
+ q->tail->next = t;
+ t->next = &q->t;
+ q->tail = t;
+}
+
+
+ /* Thread routines. */
+
+static stp_q_t stp_global_runq; /* A queue of runable threads. */
+static stp_t stp_global_main; /* Thread for the process. */
+static stp_t *stp_global_curr; /* Currently-executing thread. */
+
+static void *stp_starthelp (qt_t *old, void *ignore0, void *ignore1);
+static void stp_only (void *pu, void *pt, qt_userf_t *f);
+static void *stp_aborthelp (qt_t *sp, void *old, void *null);
+static void *stp_yieldhelp (qt_t *sp, void *old, void *blockq);
+
+
+ void
+stp_init()
+{
+ stp_qinit (&stp_global_runq);
+}
+
+
+ void
+stp_start()
+{
+ stp_t *next;
+
+ while ((next = stp_qget (&stp_global_runq)) != NULL) {
+ stp_global_curr = next;
+ QT_BLOCK (stp_starthelp, 0, 0, next->sp);
+ }
+}
+
+
+ static void *
+stp_starthelp (qt_t *old, void *ignore0, void *ignore1)
+{
+ stp_global_main.sp = old;
+ stp_qput (&stp_global_runq, &stp_global_main);
+ /* return (garbage); */
+}
+
+
+ void
+stp_create (stp_userf_t *f, void *pu)
+{
+ stp_t *t;
+ void *sto;
+
+ t = xmalloc (sizeof(stp_t));
+ t->sto = xmalloc (STP_STKSIZE);
+ sto = STP_STKALIGN (t->sto, QT_STKALIGN);
+ t->sp = QT_SP (sto, STP_STKSIZE - QT_STKALIGN);
+ t->sp = QT_ARGS (t->sp, pu, t, (qt_userf_t *)f, stp_only);
+ stp_qput (&stp_global_runq, t);
+}
+
+
+ static void
+stp_only (void *pu, void *pt, qt_userf_t *f)
+{
+ stp_global_curr = (stp_t *)pt;
+ (*(stp_userf_t *)f)(pu);
+ stp_abort();
+ /* NOTREACHED */
+}
+
+
+ void
+stp_abort (void)
+{
+ stp_t *old, *newthread;
+
+ newthread = stp_qget (&stp_global_runq);
+ old = stp_global_curr;
+ stp_global_curr = newthread;
+ QT_ABORT (stp_aborthelp, old, (void *)NULL, newthread->sp);
+}
+
+
+ static void *
+stp_aborthelp (qt_t *sp, void *old, void *null)
+{
+ free (((stp_t *)old)->sto);
+ free (old);
+ /* return (garbage); */
+}
+
+
+ void
+stp_yield()
+{
+ stp_t *old, *newthread;
+
+ newthread = stp_qget (&stp_global_runq);
+ old = stp_global_curr;
+ stp_global_curr = newthread;
+ QT_BLOCK (stp_yieldhelp, old, &stp_global_runq, newthread->sp);
+}
+
+
+ static void *
+stp_yieldhelp (qt_t *sp, void *old, void *blockq)
+{
+ ((stp_t *)old)->sp = sp;
+ stp_qput ((stp_q_t *)blockq, (stp_t *)old);
+ /* return (garbage); */
+}
diff --git a/ext/systemc/src/sysc/qt/stp.h b/ext/systemc/src/sysc/qt/stp.h
new file mode 100644
index 000000000..1220e47e2
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/stp.h
@@ -0,0 +1,51 @@
+#ifndef STP_H
+#define STP_H
+
+/*
+ * QuickThreads -- Threads-building toolkit.
+ * Copyright (c) 1993 by David Keppel
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice and this notice
+ * appear in all copies. This software is provided as a
+ * proof-of-concept and for demonstration purposes; there is no
+ * representation about the suitability of this software for any
+ * purpose.
+ */
+
+typedef struct stp_t stp_t;
+
+/* Each thread starts by calling a user-supplied function of this
+ type. */
+
+typedef void (stp_userf_t)(void *p0);
+
+/* Call this before any other primitives. */
+extern void stp_init();
+
+/* When one or more threads are created by the main thread,
+ the system goes multithread when this is called. It is done
+ (no more runable threads) when this returns. */
+
+extern void stp_start (void);
+
+/* Create a thread and make it runable. When the thread starts
+ running it will call `f' with arguments `p0' and `p1'. */
+
+extern void stp_create (stp_userf_t *f, void *p0);
+
+/* The current thread stops running but stays runable.
+ It is an error to call `stp_yield' before `stp_start'
+ is called or after `stp_start' returns. */
+
+extern void stp_yield (void);
+
+/* Like `stp_yield' but the thread is discarded. Any intermediate
+ state is lost. The thread can also terminate by simply
+ returning. */
+
+extern void stp_abort (void);
+
+
+#endif /* ndef STP_H */
diff --git a/ext/systemc/src/sysc/qt/time/README.time b/ext/systemc/src/sysc/qt/time/README.time
new file mode 100644
index 000000000..4bb190e18
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/time/README.time
@@ -0,0 +1,17 @@
+The program `raw', when run in `..' runs the program `run' produced
+from `meas.c'. It produces a raw output file (see `../tmp/*.raw').
+`raw' will die with an error if run in the current directory. Note
+that some versions of `time' produce output in an unexpected format;
+edit them by hand.
+
+`prim', `init', `cswap' and `go' produce formatted table entries used
+in the documentation (in `../doc'). For example, from `..',
+
+ foreach i (tmp/*.raw)
+ time/prim $i
+ end
+
+See notes in the QuickThreads document about the applicability of
+these microbenchmark measurements -- in general, you can expect all
+QuickThreads operations to be a bit slower when used in a real
+application.
diff --git a/ext/systemc/src/sysc/qt/time/assim b/ext/systemc/src/sysc/qt/time/assim
new file mode 100755
index 000000000..6c4c52183
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/time/assim
@@ -0,0 +1,42 @@
+#! /bin/awk -f
+
+BEGIN {
+ nmach = 0;
+
+ init_test = "1";
+ abort_test = "6";
+ blocki_test = "7";
+ block_test = "8";
+}
+
+{
+ mach = $1
+ test = $2
+ iter = $3
+ time = $6 + $8
+
+ if (machi[mach] == 0) {
+ machn[nmach] = mach;
+ machi[mach] = 1;
+ ++nmach;
+ }
+
+ us_per_op = time / iter * 1000000
+ times[mach "_" test] = us_per_op;
+}
+
+
+END {
+ for (i=0; i<nmach; ++i) {
+ m = machn[i];
+ init = times[m "_" init_test];
+ printf ("init %s | %f\n", m, init);
+
+ init_abort_blocki = times[m "_" abort_test];
+ abort_blocki = init_abort_blocki - init;
+ blocki = times[m "_" blocki_test];
+ abort = abort_blocki - blocki;
+ blockf = times[m "_" block_test];
+ printf ("swap %s | %f | %f | %f\n", m, abort, blocki, blockf);
+ }
+}
diff --git a/ext/systemc/src/sysc/qt/time/cswap b/ext/systemc/src/sysc/qt/time/cswap
new file mode 100755
index 000000000..0ec811bcd
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/time/cswap
@@ -0,0 +1,37 @@
+#! /bin/awk -f
+
+BEGIN {
+ purpose = "report time used by int only and int+fp cswaps";
+
+ nmach = 0;
+
+ test_int = "7";
+ test_fp = "8";
+}
+
+{
+ mach = $1
+ test = $2
+ iter = $3
+ time = $6 + $8
+
+ if (machi[mach] == 0) {
+ machn[nmach] = mach;
+ machi[mach] = 1;
+ ++nmach;
+ }
+
+ us_per_op = time / iter * 1000000
+ times[mach "_" test] = us_per_op;
+}
+
+
+END {
+ for (i=0; i<nmach; ++i) {
+ m = machn[i];
+
+ integer = times[m "_" test_int];
+ fp = times[m "_" test_fp];
+ printf ("%s|%3.1f|%3.1f\n", m, integer, fp);
+ }
+}
diff --git a/ext/systemc/src/sysc/qt/time/go b/ext/systemc/src/sysc/qt/time/go
new file mode 100755
index 000000000..489d53882
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/time/go
@@ -0,0 +1,43 @@
+#! /bin/awk -f
+
+BEGIN {
+ purpose = "report times used for init/start/stop";
+
+ nmach = 0;
+
+ test_single = "6";
+ test_v0 = "10";
+ test_v2 = "11";
+ test_v4 = "12";
+ test_v8 = "13";
+}
+
+{
+ mach = $1
+ test = $2
+ iter = $3
+ time = $6 + $8
+
+ if (machi[mach] == 0) {
+ machn[nmach] = mach;
+ machi[mach] = 1;
+ ++nmach;
+ }
+
+ us_per_op = time / iter * 1000000
+ times[mach "_" test] = us_per_op;
+}
+
+
+END {
+ for (i=0; i<nmach; ++i) {
+ m = machn[i];
+
+ single = times[m "_" test_single];
+ v0 = times[m "_" test_v0];
+ v2 = times[m "_" test_v2];
+ v4 = times[m "_" test_v4];
+ v8 = times[m "_" test_v8];
+ printf ("%s|%3.1f|%3.1f|%3.1f|%3.1f|%3.1f\n", m, single, v0, v2, v4, v8);
+ }
+}
diff --git a/ext/systemc/src/sysc/qt/time/init b/ext/systemc/src/sysc/qt/time/init
new file mode 100755
index 000000000..8bcbf3428
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/time/init
@@ -0,0 +1,42 @@
+#! /bin/awk -f
+
+BEGIN {
+ purpose = "Report time used to initialize a thread."
+ nmach = 0;
+
+ test_single = "1";
+ test_v0 = "14";
+ test_v2 = "15";
+ test_v4 = "16";
+ test_v8 = "17";
+}
+
+{
+ mach = $1
+ test = $2
+ iter = $3
+ time = $6 + $8
+
+ if (machi[mach] == 0) {
+ machn[nmach] = mach;
+ machi[mach] = 1;
+ ++nmach;
+ }
+
+ us_per_op = time / iter * 1000000
+ times[mach "_" test] = us_per_op;
+}
+
+
+END {
+ for (i=0; i<nmach; ++i) {
+ m = machn[i];
+
+ single = times[m "_" test_single];
+ v0 = times[m "_" test_v0];
+ v2 = times[m "_" test_v2];
+ v4 = times[m "_" test_v4];
+ v8 = times[m "_" test_v8];
+ printf ("%s|%3.1f|%3.1f|%3.1f|%3.1f|%3.1f\n", m, single, v0, v2, v4, v8);
+ }
+}
diff --git a/ext/systemc/src/sysc/qt/time/prim b/ext/systemc/src/sysc/qt/time/prim
new file mode 100755
index 000000000..22b323f6f
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/time/prim
@@ -0,0 +1,41 @@
+#! /bin/awk -f
+
+BEGIN {
+ purpose = "report times for microbenchmarks"
+
+ nmach = 0;
+
+ test_callind = "18";
+ test_callimm = "18";
+ test_addreg = "20";
+ test_loadreg = "21";
+}
+
+{
+ mach = $1
+ test = $2
+ iter = $3
+ time = $6 + $8
+
+ if (machi[mach] == 0) {
+ machn[nmach] = mach;
+ machi[mach] = 1;
+ ++nmach;
+ }
+
+ ns_per_op = time / iter * 1000000
+ times[mach "_" test] = ns_per_op;
+}
+
+
+END {
+ for (i=0; i<nmach; ++i) {
+ m = machn[i];
+
+ ind = times[m "_" test_callind];
+ imm = times[m "_" test_callimm];
+ add = times[m "_" test_addreg];
+ load = times[m "_" test_loadreg];
+ printf ("%s|%1.3f|%1.3f|%1.3f|%1.3f\n", m, ind, imm, add, load);
+ }
+}
diff --git a/ext/systemc/src/sysc/qt/time/raw b/ext/systemc/src/sysc/qt/time/raw
new file mode 100755
index 000000000..96ae10ad1
--- /dev/null
+++ b/ext/systemc/src/sysc/qt/time/raw
@@ -0,0 +1,58 @@
+#! /bin/csh
+
+rm -f timed
+
+set init=1
+set runone=6
+set blockint=7
+set blockfloat=8
+set vainit0=14
+set vainit2=15
+set vainit4=16
+set vainit8=17
+set vastart0=10
+set vastart2=11
+set vastart4=12
+set vastart8=13
+set bench_regcall=18
+set bench_immcall=19
+set bench_add=20
+set bench_load=21
+
+source configuration
+
+echo -n $config_machine $init $config_init
+/bin/time run $init $config_init
+echo -n $config_machine $runone $config_runone
+/bin/time run $runone $config_runone
+echo -n $config_machine $blockint $config_blockint
+/bin/time run $blockint $config_blockint
+echo -n $config_machine $blockfloat $config_blockfloat
+/bin/time run $blockfloat $config_blockfloat
+
+echo -n $config_machine $vainit0 $config_vainit0
+/bin/time run $vainit0 $config_vainit0
+echo -n $config_machine $vainit2 $config_vainit2
+/bin/time run $vainit2 $config_vainit2
+echo -n $config_machine $vainit4 $config_vainit4
+/bin/time run $vainit4 $config_vainit4
+echo -n $config_machine $vainit8 $config_vainit8
+/bin/time run $vainit8 $config_vainit8
+
+echo -n $config_machine $vastart0 $config_vastart0
+/bin/time run $vastart0 $config_vastart0
+echo -n $config_machine $vastart2 $config_vastart2
+/bin/time run $vastart2 $config_vastart2
+echo -n $config_machine $vastart4 $config_vastart4
+/bin/time run $vastart4 $config_vastart4
+echo -n $config_machine $vastart8 $config_vastart8
+/bin/time run $vastart8 $config_vastart8
+
+echo -n $config_machine $bench_regcall $config_bcall_reg
+/bin/time run $bench_regcall $config_bcall_reg
+echo -n $config_machine $bench_immcall $config_bcall_imm
+/bin/time run $bench_immcall $config_bcall_imm
+echo -n $config_machine $bench_add $config_b_add
+/bin/time run $bench_add $config_b_add
+echo -n $config_machine $bench_load $config_b_load
+/bin/time run $bench_load $config_b_load