summaryrefslogtreecommitdiff
path: root/lib/libc_r/arch/i386
diff options
context:
space:
mode:
authorDavid Leonard <d@cvs.openbsd.org>2000-09-25 01:16:41 +0000
committerDavid Leonard <d@cvs.openbsd.org>2000-09-25 01:16:41 +0000
commit8a4c587747beff04cc32298563b4f8f7143bf77d (patch)
treef438d7579c60a22e9eac685a2002ef79fd548f94 /lib/libc_r/arch/i386
parent3c803034c71e7476699587c4ca1885be184a8ea2 (diff)
preparation for switch-based threads
Diffstat (limited to 'lib/libc_r/arch/i386')
-rw-r--r--lib/libc_r/arch/i386/uthread_machdep.c80
-rw-r--r--lib/libc_r/arch/i386/uthread_machdep_asm.S27
2 files changed, 107 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