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 | |
parent | 3c803034c71e7476699587c4ca1885be184a8ea2 (diff) |
preparation for switch-based threads
Diffstat (limited to 'lib/libc_r/arch')
-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 | ||||
-rw-r--r-- | lib/libc_r/arch/powerpc/uthread_machdep.c | 82 | ||||
-rw-r--r-- | lib/libc_r/arch/powerpc/uthread_machdep_asm.S | 106 | ||||
-rw-r--r-- | lib/libc_r/arch/sparc/uthread_machdep.c | 44 | ||||
-rw-r--r-- | lib/libc_r/arch/sparc/uthread_machdep_asm.S | 39 |
6 files changed, 378 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 + |