summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libc_r/arch/i386/uthread_machdep.c80
-rw-r--r--lib/libc_r/arch/i386/uthread_machdep_asm.S27
-rw-r--r--lib/libc_r/arch/powerpc/uthread_machdep.c82
-rw-r--r--lib/libc_r/arch/powerpc/uthread_machdep_asm.S106
-rw-r--r--lib/libc_r/arch/sparc/uthread_machdep.c44
-rw-r--r--lib/libc_r/arch/sparc/uthread_machdep_asm.S39
-rw-r--r--lib/libpthread/arch/i386/uthread_machdep.c80
-rw-r--r--lib/libpthread/arch/i386/uthread_machdep_asm.S27
-rw-r--r--lib/libpthread/arch/powerpc/uthread_machdep.c82
-rw-r--r--lib/libpthread/arch/powerpc/uthread_machdep_asm.S106
-rw-r--r--lib/libpthread/arch/sparc/uthread_machdep.c44
-rw-r--r--lib/libpthread/arch/sparc/uthread_machdep_asm.S39
12 files changed, 756 insertions, 0 deletions
diff --git a/lib/libc_r/arch/i386/uthread_machdep.c b/lib/libc_r/arch/i386/uthread_machdep.c
new file mode 100644
index 00000000000..6535e2f73d8
--- /dev/null
+++ b/lib/libc_r/arch/i386/uthread_machdep.c
@@ -0,0 +1,80 @@
+/* $OpenBSD: uthread_machdep.c,v 1.1 2000/09/25 01:16:40 d Exp $ */
+/* David Leonard, <d@csee.uq.edu.au>. Public domain. */
+
+/*
+ * Machine-dependent thread state functions for OpenBSD/sparc.
+ */
+
+#include <machine/param.h>
+#include <pthread.h>
+#include "pthread_private.h"
+
+struct frame {
+ int fr_gs;
+ int fr_fs;
+ int fr_es;
+ int fr_ds;
+
+ int fr_edi;
+ int fr_esi;
+ int fr_ebp;
+ int fr_esp;
+ int fr_ebx;
+ int fr_edx;
+ int fr_ecx;
+ int fr_eax;
+
+ int fr_eip;
+ int fr_cs; /* XXX unreachable? */
+};
+
+#define copyreg(reg, lval) \
+ __asm__("mov %%" #reg ", %0" : "=g"(lval))
+
+/*
+ * Given a stack and an entry function, initialise a state
+ * structure that can be later switched to.
+ */
+void
+_thread_machdep_init(statep, base, len, entry)
+ struct _machdep_state* statep;
+ void *base;
+ int len;
+ void (*entry)(void);
+{
+ struct frame *f;
+
+ /* Locate the initial frame, aligned at the top of the stack */
+ f = (struct frame *)(((int)base + len - sizeof *f) & ~ALIGNBYTES);
+
+ /* Set up initial frame */
+ f->fr_esp = (int)&f->fr_edi;
+ copyreg(cs, f->fr_cs);
+ copyreg(ds, f->fr_ds);
+ copyreg(es, f->fr_es);
+ copyreg(fs, f->fr_fs);
+ copyreg(gs, f->fr_gs);
+ f->fr_ebp = (int)-1;
+ f->fr_eip = (int)entry;
+
+ statep->esp = (int)f;
+}
+
+void
+_thread_machdep_save_float_state(ms)
+ struct _machdep_state *ms;
+{
+ char *fdata = (char *)&ms->fpreg;
+
+ __asm__("fsave %0"::"m" (*fdata));
+}
+
+void
+_thread_machdep_restore_float_state(ms)
+ struct _machdep_state *ms;
+{
+ char *fdata = (char *)&ms->fpreg;
+
+ __asm__("frstor %0"::"m" (*fdata));
+}
+
diff --git a/lib/libc_r/arch/i386/uthread_machdep_asm.S b/lib/libc_r/arch/i386/uthread_machdep_asm.S
new file mode 100644
index 00000000000..06652fd210f
--- /dev/null
+++ b/lib/libc_r/arch/i386/uthread_machdep_asm.S
@@ -0,0 +1,27 @@
+/* $OpenBSD: uthread_machdep_asm.S,v 1.1 2000/09/25 01:16:40 d Exp $ */
+/* David Leonard, <d@csee.uq.edu.au>. Public domain. */
+
+#include <machine/asm.h>
+
+/*
+ * Switch stacks
+ */
+
+/* void _thread_machdep_switch(new, oldsave); */
+ENTRY(_thread_machdep_switch)
+ pushal /* pushl %eax,%ecx,%edx,%ebx,%esp,%ebp,%esi,%edi */
+ pushl %ds
+ pushl %es
+ pushl %fs
+ pushl %gs
+#define DISTANCE ((8+1+1+1+1)*4)
+ movl (DISTANCE+8)(%esp), %eax /* %eax = arg2 */
+ movl %esp, 0(%eax) /* *arg2 = %esp */
+ movl (DISTANCE+4)(%esp), %eax /* %eax = arg1 */
+ movl 0(%eax), %esp /* %esp = *arg1 */
+ popl %gs
+ popl %fs
+ popl %es
+ popl %ds
+ popal /* popl %edi,%esi,%ebp,%esp,%ebx,%edx,%ecx,%eax */
+ ret
diff --git a/lib/libc_r/arch/powerpc/uthread_machdep.c b/lib/libc_r/arch/powerpc/uthread_machdep.c
new file mode 100644
index 00000000000..e7137e20d11
--- /dev/null
+++ b/lib/libc_r/arch/powerpc/uthread_machdep.c
@@ -0,0 +1,82 @@
+/* $OpenBSD: uthread_machdep.c,v 1.1 2000/09/25 01:16:40 d Exp $ */
+/* David Leonard, <d@csee.uq.edu.au>. Public domain */
+
+#include <pthread.h>
+#include "pthread_private.h"
+
+#define ALIGNBYTES 0xf
+
+/* Register save frame as it appears on the stack */
+struct _machdep_frame {
+ int r1;
+ int reserved;
+ int gp[32-14];
+ int lr, cr, ctr, xer;
+ long fp[32-14];
+ long fs;
+ /* The rest are only valid in the initial frame */
+ int next_r1;
+ int next_lr;
+};
+
+/*
+ * Given a stack and an entry function, initialise a state
+ * structure that can be later switched to.
+ */
+void
+_thread_machdep_init(statep, base, len, entry)
+ struct _machdep_state* statep;
+ void *base;
+ int len;
+ void (*entry)(void);
+{
+ struct _machdep_frame *f;
+
+ /* Locate the initial frame, aligned at the top of the stack */
+ f = (struct _machdep_frame *)(((int)base + len - sizeof *f) & ~ALIGNBYTES);
+
+ f->r1 = (int)&f->next_r1;
+ f->reserved = 0;
+ f->lr = (int)entry;
+ f->next_r1 = 0; /* for gdb */
+ f->next_lr = 0; /* for gdb */
+
+ /* Initialise the new thread with all the state from this thread. */
+
+#define copyreg(x) __asm__("stw " #x ", %0" : "=m"(f->gp[x-14]))
+ copyreg(14); copyreg(15); copyreg(16); copyreg(17); copyreg(18);
+ copyreg(19); copyreg(20); copyreg(21); copyreg(22); copyreg(23);
+ copyreg(24); copyreg(25); copyreg(26); copyreg(27); copyreg(28);
+ copyreg(29); copyreg(30); copyreg(31);
+
+#define copysreg(nm) __asm__("mf" #nm " %0" : "=r"(f->nm))
+ copysreg(cr); copysreg(ctr); copysreg(xer);
+
+#define copyfreg(x) __asm__("stfd " #x ", %0" : "=m"(f->fp[x-14]))
+ copyfreg(14); copyfreg(15); copyfreg(16); copyfreg(17); copyfreg(18);
+ copyfreg(19); copyfreg(20); copyfreg(21); copyfreg(22); copyfreg(23);
+ copyfreg(24); copyfreg(25); copyfreg(26); copyfreg(27); copyfreg(28);
+ copyfreg(29); copyfreg(30); copyfreg(31);
+
+ __asm__("mffs 0; stfd 0, %0" : "=m"(f->fs));
+
+ statep->frame = (int)f;
+}
+
+
+/*
+ * No-op float saves.
+ * (Floating point registers were saved in _thread_machdep_switch())
+ */
+
+void
+_thread_machdep_save_float_state(statep)
+ struct _machdep_state* statep;
+{
+}
+
+void
+_thread_machdep_restore_float_state(statep)
+ struct _machdep_state* statep;
+{
+}
diff --git a/lib/libc_r/arch/powerpc/uthread_machdep_asm.S b/lib/libc_r/arch/powerpc/uthread_machdep_asm.S
new file mode 100644
index 00000000000..21cd4f0889e
--- /dev/null
+++ b/lib/libc_r/arch/powerpc/uthread_machdep_asm.S
@@ -0,0 +1,106 @@
+/* $OpenBSD: uthread_machdep_asm.S,v 1.1 2000/09/25 01:16:40 d Exp $ */
+/* David Leonard, <d@csee.uq.edu.au>. Public domain. */
+
+#include <machine/asm.h>
+
+/* These need to be kept in sync with uthread_machdep.c */
+#define REGOFF(n) (2*4 + (n-14)*4)
+#define FPOFF(n) (REGOFF(36) + (n-14)*4)
+#define FRAMESIZE FPOFF(33)
+
+#define SA(x) (((x)+0xf)&~0xf)
+
+ENTRY(_thread_machdep_switch)
+ stwu 1, -SA(FRAMESIZE)(1)
+
+ /* Save context into frame */
+ stw 14, REGOFF(14)(1)
+ stw 15, REGOFF(15)(1)
+ stw 16, REGOFF(16)(1)
+ stw 17, REGOFF(17)(1)
+ stw 18, REGOFF(18)(1)
+ stw 19, REGOFF(19)(1)
+ stw 20, REGOFF(20)(1)
+ stw 21, REGOFF(21)(1)
+ stw 22, REGOFF(22)(1)
+ stw 23, REGOFF(23)(1)
+ stw 24, REGOFF(24)(1)
+ stw 25, REGOFF(25)(1)
+ stw 26, REGOFF(26)(1)
+ stw 27, REGOFF(27)(1)
+ stw 28, REGOFF(28)(1)
+ stw 29, REGOFF(29)(1)
+ stw 30, REGOFF(30)(1)
+ stw 31, REGOFF(31)(1)
+ mflr 0; stw 0, REGOFF(32)(1)
+ mfcr 0; stw 0, REGOFF(33)(1)
+ mfctr 0; stw 0, REGOFF(34)(1)
+ mfxer 0; stw 0, REGOFF(35)(1)
+ stfd 14, FPOFF(14)(1)
+ stfd 15, FPOFF(15)(1)
+ stfd 16, FPOFF(16)(1)
+ stfd 17, FPOFF(17)(1)
+ stfd 18, FPOFF(18)(1)
+ stfd 19, FPOFF(19)(1)
+ stfd 20, FPOFF(20)(1)
+ stfd 21, FPOFF(21)(1)
+ stfd 22, FPOFF(22)(1)
+ stfd 23, FPOFF(23)(1)
+ stfd 24, FPOFF(24)(1)
+ stfd 25, FPOFF(25)(1)
+ stfd 26, FPOFF(26)(1)
+ stfd 27, FPOFF(27)(1)
+ stfd 28, FPOFF(28)(1)
+ stfd 29, FPOFF(29)(1)
+ stfd 30, FPOFF(30)(1)
+ stfd 31, FPOFF(31)(1)
+ mffs 0; stfd 0, FPOFF(32)(1)
+
+ /* Switch stacks */
+ stw 1, 0(4)
+ lwz 1, 0(3)
+
+ /* Restore context from the frame */
+ lfd 0, FPOFF(32)(1); mtfsf 0xff, 0
+ lfd 31, FPOFF(31)(1)
+ lfd 30, FPOFF(30)(1)
+ lfd 29, FPOFF(29)(1)
+ lfd 28, FPOFF(28)(1)
+ lfd 27, FPOFF(27)(1)
+ lfd 26, FPOFF(26)(1)
+ lfd 25, FPOFF(25)(1)
+ lfd 24, FPOFF(24)(1)
+ lfd 23, FPOFF(23)(1)
+ lfd 22, FPOFF(22)(1)
+ lfd 21, FPOFF(21)(1)
+ lfd 20, FPOFF(20)(1)
+ lfd 19, FPOFF(19)(1)
+ lfd 18, FPOFF(18)(1)
+ lfd 17, FPOFF(17)(1)
+ lfd 16, FPOFF(16)(1)
+ lfd 15, FPOFF(15)(1)
+ lfd 14, FPOFF(14)(1)
+ lwz 0, REGOFF(35)(1); mtxer 0
+ lwz 0, REGOFF(34)(1); mtctr 0
+ lwz 0, REGOFF(33)(1); mtcr 0
+ lwz 0, REGOFF(32)(1); mtlr 0
+ lwz 31, REGOFF(31)(1)
+ lwz 30, REGOFF(30)(1)
+ lwz 29, REGOFF(29)(1)
+ lwz 28, REGOFF(28)(1)
+ lwz 27, REGOFF(27)(1)
+ lwz 26, REGOFF(26)(1)
+ lwz 25, REGOFF(25)(1)
+ lwz 24, REGOFF(24)(1)
+ lwz 23, REGOFF(23)(1)
+ lwz 22, REGOFF(22)(1)
+ lwz 21, REGOFF(21)(1)
+ lwz 20, REGOFF(20)(1)
+ lwz 19, REGOFF(19)(1)
+ lwz 18, REGOFF(18)(1)
+ lwz 17, REGOFF(17)(1)
+ lwz 16, REGOFF(16)(1)
+ lwz 15, REGOFF(15)(1)
+ lwz 14, REGOFF(14)(1)
+ la 1, SA(FRAMESIZE)(1)
+ blr
diff --git a/lib/libc_r/arch/sparc/uthread_machdep.c b/lib/libc_r/arch/sparc/uthread_machdep.c
new file mode 100644
index 00000000000..789a1d3efd1
--- /dev/null
+++ b/lib/libc_r/arch/sparc/uthread_machdep.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: uthread_machdep.c,v 1.1 2000/09/25 01:16:40 d Exp $ */
+
+/*
+ * Machine-dependent thread state functions for OpenBSD/sparc.
+ */
+
+#include <machine/frame.h>
+#include <machine/param.h>
+#include <pthread.h>
+#include "pthread_private.h"
+
+/*
+ * Given a stack and an entry function, initialise a state
+ * structure that can be later switched to.
+ */
+void
+_thread_machdep_init(statep, base, len, entry)
+ struct _machdep_state* statep;
+ void *base;
+ int len;
+ void (*entry)(void);
+{
+ struct frame *f;
+
+ /* Locate the initial frame, aligned at the top of the stack */
+ f = (struct frame *)(((int)base + len - sizeof *f) & ~ALIGNBYTES);
+
+ f->fr_fp = (struct frame *)-1; /* purposefully misaligned */
+ f->fr_pc = -1; /* for gdb */
+ statep->fp = (int)f;
+ statep->pc = -8 + (int)entry;
+}
+
+void
+_thread_machdep_save_float_state(statep)
+ struct _machdep_state* statep;
+{
+}
+
+void
+_thread_machdep_restore_float_state(statep)
+ struct _machdep_state* statep;
+{
+}
diff --git a/lib/libc_r/arch/sparc/uthread_machdep_asm.S b/lib/libc_r/arch/sparc/uthread_machdep_asm.S
new file mode 100644
index 00000000000..27be8c45311
--- /dev/null
+++ b/lib/libc_r/arch/sparc/uthread_machdep_asm.S
@@ -0,0 +1,39 @@
+/* $OpenBSD: uthread_machdep_asm.S,v 1.1 2000/09/25 01:16:40 d Exp $ */
+/* David Leonard <d@csee.uq.edu.au>. Public domain. */
+
+#include <machine/asm.h>
+#include <machine/trap.h>
+
+/*
+ * Switch stacks.
+ * On sparc this also means we switch register windows.
+ */
+
+#ifdef __sparc_v9__
+#define flushw .word 0x81580000
+#else
+#define flushw t T_FLUSHWIN
+#endif
+
+#define SA(x) (((x)+15)&(~0x1f))
+#define MINFRAME ((16+1+6)*8)
+
+/* void _thread_switch(int newstate[2], int savestate[2], int flags); */
+ENTRY(_thread_machdep_switch)
+
+ /* new window */
+ save %sp, -SA(MINFRAME), %sp
+
+ /* flush all windows (except current one) into memory frames */
+ flushw
+
+ /* switch the stack pointer and return address */
+ st %fp, [%i1 + 0]
+ st %i7, [%i1 + 4]
+ ld [%i0 + 0], %fp
+ ld [%i0 + 4], %i7
+
+ /* return to saved window at new %fp */
+ ret
+ restore
+
diff --git a/lib/libpthread/arch/i386/uthread_machdep.c b/lib/libpthread/arch/i386/uthread_machdep.c
new file mode 100644
index 00000000000..6535e2f73d8
--- /dev/null
+++ b/lib/libpthread/arch/i386/uthread_machdep.c
@@ -0,0 +1,80 @@
+/* $OpenBSD: uthread_machdep.c,v 1.1 2000/09/25 01:16:40 d Exp $ */
+/* David Leonard, <d@csee.uq.edu.au>. Public domain. */
+
+/*
+ * Machine-dependent thread state functions for OpenBSD/sparc.
+ */
+
+#include <machine/param.h>
+#include <pthread.h>
+#include "pthread_private.h"
+
+struct frame {
+ int fr_gs;
+ int fr_fs;
+ int fr_es;
+ int fr_ds;
+
+ int fr_edi;
+ int fr_esi;
+ int fr_ebp;
+ int fr_esp;
+ int fr_ebx;
+ int fr_edx;
+ int fr_ecx;
+ int fr_eax;
+
+ int fr_eip;
+ int fr_cs; /* XXX unreachable? */
+};
+
+#define copyreg(reg, lval) \
+ __asm__("mov %%" #reg ", %0" : "=g"(lval))
+
+/*
+ * Given a stack and an entry function, initialise a state
+ * structure that can be later switched to.
+ */
+void
+_thread_machdep_init(statep, base, len, entry)
+ struct _machdep_state* statep;
+ void *base;
+ int len;
+ void (*entry)(void);
+{
+ struct frame *f;
+
+ /* Locate the initial frame, aligned at the top of the stack */
+ f = (struct frame *)(((int)base + len - sizeof *f) & ~ALIGNBYTES);
+
+ /* Set up initial frame */
+ f->fr_esp = (int)&f->fr_edi;
+ copyreg(cs, f->fr_cs);
+ copyreg(ds, f->fr_ds);
+ copyreg(es, f->fr_es);
+ copyreg(fs, f->fr_fs);
+ copyreg(gs, f->fr_gs);
+ f->fr_ebp = (int)-1;
+ f->fr_eip = (int)entry;
+
+ statep->esp = (int)f;
+}
+
+void
+_thread_machdep_save_float_state(ms)
+ struct _machdep_state *ms;
+{
+ char *fdata = (char *)&ms->fpreg;
+
+ __asm__("fsave %0"::"m" (*fdata));
+}
+
+void
+_thread_machdep_restore_float_state(ms)
+ struct _machdep_state *ms;
+{
+ char *fdata = (char *)&ms->fpreg;
+
+ __asm__("frstor %0"::"m" (*fdata));
+}
+
diff --git a/lib/libpthread/arch/i386/uthread_machdep_asm.S b/lib/libpthread/arch/i386/uthread_machdep_asm.S
new file mode 100644
index 00000000000..06652fd210f
--- /dev/null
+++ b/lib/libpthread/arch/i386/uthread_machdep_asm.S
@@ -0,0 +1,27 @@
+/* $OpenBSD: uthread_machdep_asm.S,v 1.1 2000/09/25 01:16:40 d Exp $ */
+/* David Leonard, <d@csee.uq.edu.au>. Public domain. */
+
+#include <machine/asm.h>
+
+/*
+ * Switch stacks
+ */
+
+/* void _thread_machdep_switch(new, oldsave); */
+ENTRY(_thread_machdep_switch)
+ pushal /* pushl %eax,%ecx,%edx,%ebx,%esp,%ebp,%esi,%edi */
+ pushl %ds
+ pushl %es
+ pushl %fs
+ pushl %gs
+#define DISTANCE ((8+1+1+1+1)*4)
+ movl (DISTANCE+8)(%esp), %eax /* %eax = arg2 */
+ movl %esp, 0(%eax) /* *arg2 = %esp */
+ movl (DISTANCE+4)(%esp), %eax /* %eax = arg1 */
+ movl 0(%eax), %esp /* %esp = *arg1 */
+ popl %gs
+ popl %fs
+ popl %es
+ popl %ds
+ popal /* popl %edi,%esi,%ebp,%esp,%ebx,%edx,%ecx,%eax */
+ ret
diff --git a/lib/libpthread/arch/powerpc/uthread_machdep.c b/lib/libpthread/arch/powerpc/uthread_machdep.c
new file mode 100644
index 00000000000..e7137e20d11
--- /dev/null
+++ b/lib/libpthread/arch/powerpc/uthread_machdep.c
@@ -0,0 +1,82 @@
+/* $OpenBSD: uthread_machdep.c,v 1.1 2000/09/25 01:16:40 d Exp $ */
+/* David Leonard, <d@csee.uq.edu.au>. Public domain */
+
+#include <pthread.h>
+#include "pthread_private.h"
+
+#define ALIGNBYTES 0xf
+
+/* Register save frame as it appears on the stack */
+struct _machdep_frame {
+ int r1;
+ int reserved;
+ int gp[32-14];
+ int lr, cr, ctr, xer;
+ long fp[32-14];
+ long fs;
+ /* The rest are only valid in the initial frame */
+ int next_r1;
+ int next_lr;
+};
+
+/*
+ * Given a stack and an entry function, initialise a state
+ * structure that can be later switched to.
+ */
+void
+_thread_machdep_init(statep, base, len, entry)
+ struct _machdep_state* statep;
+ void *base;
+ int len;
+ void (*entry)(void);
+{
+ struct _machdep_frame *f;
+
+ /* Locate the initial frame, aligned at the top of the stack */
+ f = (struct _machdep_frame *)(((int)base + len - sizeof *f) & ~ALIGNBYTES);
+
+ f->r1 = (int)&f->next_r1;
+ f->reserved = 0;
+ f->lr = (int)entry;
+ f->next_r1 = 0; /* for gdb */
+ f->next_lr = 0; /* for gdb */
+
+ /* Initialise the new thread with all the state from this thread. */
+
+#define copyreg(x) __asm__("stw " #x ", %0" : "=m"(f->gp[x-14]))
+ copyreg(14); copyreg(15); copyreg(16); copyreg(17); copyreg(18);
+ copyreg(19); copyreg(20); copyreg(21); copyreg(22); copyreg(23);
+ copyreg(24); copyreg(25); copyreg(26); copyreg(27); copyreg(28);
+ copyreg(29); copyreg(30); copyreg(31);
+
+#define copysreg(nm) __asm__("mf" #nm " %0" : "=r"(f->nm))
+ copysreg(cr); copysreg(ctr); copysreg(xer);
+
+#define copyfreg(x) __asm__("stfd " #x ", %0" : "=m"(f->fp[x-14]))
+ copyfreg(14); copyfreg(15); copyfreg(16); copyfreg(17); copyfreg(18);
+ copyfreg(19); copyfreg(20); copyfreg(21); copyfreg(22); copyfreg(23);
+ copyfreg(24); copyfreg(25); copyfreg(26); copyfreg(27); copyfreg(28);
+ copyfreg(29); copyfreg(30); copyfreg(31);
+
+ __asm__("mffs 0; stfd 0, %0" : "=m"(f->fs));
+
+ statep->frame = (int)f;
+}
+
+
+/*
+ * No-op float saves.
+ * (Floating point registers were saved in _thread_machdep_switch())
+ */
+
+void
+_thread_machdep_save_float_state(statep)
+ struct _machdep_state* statep;
+{
+}
+
+void
+_thread_machdep_restore_float_state(statep)
+ struct _machdep_state* statep;
+{
+}
diff --git a/lib/libpthread/arch/powerpc/uthread_machdep_asm.S b/lib/libpthread/arch/powerpc/uthread_machdep_asm.S
new file mode 100644
index 00000000000..21cd4f0889e
--- /dev/null
+++ b/lib/libpthread/arch/powerpc/uthread_machdep_asm.S
@@ -0,0 +1,106 @@
+/* $OpenBSD: uthread_machdep_asm.S,v 1.1 2000/09/25 01:16:40 d Exp $ */
+/* David Leonard, <d@csee.uq.edu.au>. Public domain. */
+
+#include <machine/asm.h>
+
+/* These need to be kept in sync with uthread_machdep.c */
+#define REGOFF(n) (2*4 + (n-14)*4)
+#define FPOFF(n) (REGOFF(36) + (n-14)*4)
+#define FRAMESIZE FPOFF(33)
+
+#define SA(x) (((x)+0xf)&~0xf)
+
+ENTRY(_thread_machdep_switch)
+ stwu 1, -SA(FRAMESIZE)(1)
+
+ /* Save context into frame */
+ stw 14, REGOFF(14)(1)
+ stw 15, REGOFF(15)(1)
+ stw 16, REGOFF(16)(1)
+ stw 17, REGOFF(17)(1)
+ stw 18, REGOFF(18)(1)
+ stw 19, REGOFF(19)(1)
+ stw 20, REGOFF(20)(1)
+ stw 21, REGOFF(21)(1)
+ stw 22, REGOFF(22)(1)
+ stw 23, REGOFF(23)(1)
+ stw 24, REGOFF(24)(1)
+ stw 25, REGOFF(25)(1)
+ stw 26, REGOFF(26)(1)
+ stw 27, REGOFF(27)(1)
+ stw 28, REGOFF(28)(1)
+ stw 29, REGOFF(29)(1)
+ stw 30, REGOFF(30)(1)
+ stw 31, REGOFF(31)(1)
+ mflr 0; stw 0, REGOFF(32)(1)
+ mfcr 0; stw 0, REGOFF(33)(1)
+ mfctr 0; stw 0, REGOFF(34)(1)
+ mfxer 0; stw 0, REGOFF(35)(1)
+ stfd 14, FPOFF(14)(1)
+ stfd 15, FPOFF(15)(1)
+ stfd 16, FPOFF(16)(1)
+ stfd 17, FPOFF(17)(1)
+ stfd 18, FPOFF(18)(1)
+ stfd 19, FPOFF(19)(1)
+ stfd 20, FPOFF(20)(1)
+ stfd 21, FPOFF(21)(1)
+ stfd 22, FPOFF(22)(1)
+ stfd 23, FPOFF(23)(1)
+ stfd 24, FPOFF(24)(1)
+ stfd 25, FPOFF(25)(1)
+ stfd 26, FPOFF(26)(1)
+ stfd 27, FPOFF(27)(1)
+ stfd 28, FPOFF(28)(1)
+ stfd 29, FPOFF(29)(1)
+ stfd 30, FPOFF(30)(1)
+ stfd 31, FPOFF(31)(1)
+ mffs 0; stfd 0, FPOFF(32)(1)
+
+ /* Switch stacks */
+ stw 1, 0(4)
+ lwz 1, 0(3)
+
+ /* Restore context from the frame */
+ lfd 0, FPOFF(32)(1); mtfsf 0xff, 0
+ lfd 31, FPOFF(31)(1)
+ lfd 30, FPOFF(30)(1)
+ lfd 29, FPOFF(29)(1)
+ lfd 28, FPOFF(28)(1)
+ lfd 27, FPOFF(27)(1)
+ lfd 26, FPOFF(26)(1)
+ lfd 25, FPOFF(25)(1)
+ lfd 24, FPOFF(24)(1)
+ lfd 23, FPOFF(23)(1)
+ lfd 22, FPOFF(22)(1)
+ lfd 21, FPOFF(21)(1)
+ lfd 20, FPOFF(20)(1)
+ lfd 19, FPOFF(19)(1)
+ lfd 18, FPOFF(18)(1)
+ lfd 17, FPOFF(17)(1)
+ lfd 16, FPOFF(16)(1)
+ lfd 15, FPOFF(15)(1)
+ lfd 14, FPOFF(14)(1)
+ lwz 0, REGOFF(35)(1); mtxer 0
+ lwz 0, REGOFF(34)(1); mtctr 0
+ lwz 0, REGOFF(33)(1); mtcr 0
+ lwz 0, REGOFF(32)(1); mtlr 0
+ lwz 31, REGOFF(31)(1)
+ lwz 30, REGOFF(30)(1)
+ lwz 29, REGOFF(29)(1)
+ lwz 28, REGOFF(28)(1)
+ lwz 27, REGOFF(27)(1)
+ lwz 26, REGOFF(26)(1)
+ lwz 25, REGOFF(25)(1)
+ lwz 24, REGOFF(24)(1)
+ lwz 23, REGOFF(23)(1)
+ lwz 22, REGOFF(22)(1)
+ lwz 21, REGOFF(21)(1)
+ lwz 20, REGOFF(20)(1)
+ lwz 19, REGOFF(19)(1)
+ lwz 18, REGOFF(18)(1)
+ lwz 17, REGOFF(17)(1)
+ lwz 16, REGOFF(16)(1)
+ lwz 15, REGOFF(15)(1)
+ lwz 14, REGOFF(14)(1)
+ la 1, SA(FRAMESIZE)(1)
+ blr
diff --git a/lib/libpthread/arch/sparc/uthread_machdep.c b/lib/libpthread/arch/sparc/uthread_machdep.c
new file mode 100644
index 00000000000..789a1d3efd1
--- /dev/null
+++ b/lib/libpthread/arch/sparc/uthread_machdep.c
@@ -0,0 +1,44 @@
+/* $OpenBSD: uthread_machdep.c,v 1.1 2000/09/25 01:16:40 d Exp $ */
+
+/*
+ * Machine-dependent thread state functions for OpenBSD/sparc.
+ */
+
+#include <machine/frame.h>
+#include <machine/param.h>
+#include <pthread.h>
+#include "pthread_private.h"
+
+/*
+ * Given a stack and an entry function, initialise a state
+ * structure that can be later switched to.
+ */
+void
+_thread_machdep_init(statep, base, len, entry)
+ struct _machdep_state* statep;
+ void *base;
+ int len;
+ void (*entry)(void);
+{
+ struct frame *f;
+
+ /* Locate the initial frame, aligned at the top of the stack */
+ f = (struct frame *)(((int)base + len - sizeof *f) & ~ALIGNBYTES);
+
+ f->fr_fp = (struct frame *)-1; /* purposefully misaligned */
+ f->fr_pc = -1; /* for gdb */
+ statep->fp = (int)f;
+ statep->pc = -8 + (int)entry;
+}
+
+void
+_thread_machdep_save_float_state(statep)
+ struct _machdep_state* statep;
+{
+}
+
+void
+_thread_machdep_restore_float_state(statep)
+ struct _machdep_state* statep;
+{
+}
diff --git a/lib/libpthread/arch/sparc/uthread_machdep_asm.S b/lib/libpthread/arch/sparc/uthread_machdep_asm.S
new file mode 100644
index 00000000000..27be8c45311
--- /dev/null
+++ b/lib/libpthread/arch/sparc/uthread_machdep_asm.S
@@ -0,0 +1,39 @@
+/* $OpenBSD: uthread_machdep_asm.S,v 1.1 2000/09/25 01:16:40 d Exp $ */
+/* David Leonard <d@csee.uq.edu.au>. Public domain. */
+
+#include <machine/asm.h>
+#include <machine/trap.h>
+
+/*
+ * Switch stacks.
+ * On sparc this also means we switch register windows.
+ */
+
+#ifdef __sparc_v9__
+#define flushw .word 0x81580000
+#else
+#define flushw t T_FLUSHWIN
+#endif
+
+#define SA(x) (((x)+15)&(~0x1f))
+#define MINFRAME ((16+1+6)*8)
+
+/* void _thread_switch(int newstate[2], int savestate[2], int flags); */
+ENTRY(_thread_machdep_switch)
+
+ /* new window */
+ save %sp, -SA(MINFRAME), %sp
+
+ /* flush all windows (except current one) into memory frames */
+ flushw
+
+ /* switch the stack pointer and return address */
+ st %fp, [%i1 + 0]
+ st %i7, [%i1 + 4]
+ ld [%i0 + 0], %fp
+ ld [%i0 + 4], %i7
+
+ /* return to saved window at new %fp */
+ ret
+ restore
+