diff options
author | David Leonard <d@cvs.openbsd.org> | 2000-09-25 01:16:41 +0000 |
---|---|---|
committer | David Leonard <d@cvs.openbsd.org> | 2000-09-25 01:16:41 +0000 |
commit | 8a4c587747beff04cc32298563b4f8f7143bf77d (patch) | |
tree | f438d7579c60a22e9eac685a2002ef79fd548f94 /lib/libc_r/arch/i386 | |
parent | 3c803034c71e7476699587c4ca1885be184a8ea2 (diff) |
preparation for switch-based threads
Diffstat (limited to 'lib/libc_r/arch/i386')
-rw-r--r-- | lib/libc_r/arch/i386/uthread_machdep.c | 80 | ||||
-rw-r--r-- | lib/libc_r/arch/i386/uthread_machdep_asm.S | 27 |
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 |