where it belongs. Code looks fishy. Untested. (initcontext, startpoint): Internal linkage.
329 lines
8.4 KiB
C
329 lines
8.4 KiB
C
/*
|
|
* Empire - A multi-player, client/server Internet based war game.
|
|
* Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
|
|
* Ken Stevens, Steve McClure
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* ---
|
|
*
|
|
* See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
|
|
* related information and legal notices. It is expected that any future
|
|
* projects/authors will amend these files as needed.
|
|
*
|
|
* ---
|
|
*
|
|
* arch.c: architecture-dependant process context code
|
|
*
|
|
* Known contributors to this file:
|
|
* Dave Pare, 1994
|
|
* Steve McClure, 1994-2000
|
|
*/
|
|
|
|
#include "prototypes.h"
|
|
|
|
#if defined(_EMPTH_LWP)
|
|
|
|
#include "lwp.h"
|
|
#include "lwpint.h"
|
|
|
|
/*
|
|
* Implement machine-dependent functions lwpInitContext(), lwpSave(),
|
|
* lwpRestore().
|
|
*
|
|
* If lwpSave() and lwpRestore() are #def'd to setjmp() and longjmp(),
|
|
* then lwpInitContext() needs to set up the jmp_buf for a longjmp(),
|
|
* similar to setjmp(). To figure that out for another machine, check
|
|
* their source or reverse engineer.
|
|
*/
|
|
|
|
|
|
#if defined UCONTEXT
|
|
/*
|
|
* Alternate aproach using setcontext and getcontext instead of setjmp and
|
|
* longjump. This should work on any SVr4 machine independant of
|
|
* architecture. Unfortunately some changes are still nessesary in lwp.c.
|
|
* Tested on IRIX 5.3
|
|
*/
|
|
|
|
void
|
|
lwpInitContext(struct lwpProc *newp, stack_t *spp)
|
|
{
|
|
getcontext(&newp->context);
|
|
newp->context.uc_stack.ss_sp = spp->ss_sp;
|
|
newp->context.uc_stack.ss_size = spp->ss_size;
|
|
makecontext(&newp->context, lwpEntryPoint, 0);
|
|
}
|
|
|
|
#elif defined(hpc)
|
|
|
|
static struct lwpProc *tempcontext;
|
|
static struct lwpProc *initcontext = NULL;
|
|
static int startpoint;
|
|
|
|
static void
|
|
startcontext(void)
|
|
{
|
|
int space[10000];
|
|
int x;
|
|
|
|
startpoint = (void *)&x;
|
|
if (!setjmp(initcontext->context))
|
|
longjmp(tempcontext->context, 1);
|
|
|
|
if (!setjmp(tempcontext->context))
|
|
longjmp(LwpCurrent->context, 1);
|
|
|
|
lwpEntryPoint();
|
|
}
|
|
|
|
void
|
|
lwpInitContext(struct lwpProc *newp, void *sp)
|
|
{
|
|
struct lwpProc holder;
|
|
int endpoint;
|
|
|
|
if (initcontext == NULL) {
|
|
initcontext = malloc(sizeof(struct lwpProc));
|
|
tempcontext = &holder;
|
|
if (!setjmp(tempcontext->context))
|
|
startcontext();
|
|
}
|
|
|
|
tempcontext = newp;
|
|
endpoint = &endpoint;
|
|
if (endpoint < startpoint) {
|
|
if (!setjmp(LwpCurrent->context))
|
|
longjmp(initcontext->context, 1);
|
|
} else {
|
|
LwpCurrent->size = endpoint - startpoint;
|
|
LwpCurrent->sbtm = realloc(LwpCurrent->sbtm, LwpCurrent->size);
|
|
memcpy(LwpCurrent->sbtm, startpoint, LwpCurrent->size);
|
|
if (!setjmp(LwpCurrent->context))
|
|
longjmp(initcontext->context, 1);
|
|
memcpy(startpoint, LwpCurrent->sbtm, LwpCurrent->size);
|
|
}
|
|
}
|
|
|
|
int
|
|
lwpSave(jmp_buf jb)
|
|
{
|
|
int endpoint;
|
|
|
|
endpoint = &endpoint;
|
|
if (initcontext == NULL || endpoint < startpoint)
|
|
return setjmp(jb, 1);
|
|
|
|
LwpCurrent->size = endpoint - startpoint;
|
|
LwpCurrent->sbtm = realloc(LwpCurrent->sbtm, LwpCurrent->size);
|
|
memcpy(LwpCurrent->sbtm, startpoint, LwpCurrent->size);
|
|
if (setjmp(jb, 1)) {
|
|
memcpy(startpoint, LwpCurrent->sbtm, LwpCurrent->size);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#elif defined(hpux)
|
|
|
|
void
|
|
lwpInitContext(volatile struct lwpProc *volatile newp, void *sp)
|
|
{
|
|
static jmp_buf *cpp;
|
|
|
|
if (!lwpSave(LwpCurrent->context)) {
|
|
cpp = (jmp_buf *) & newp->context;
|
|
asm volatile ("ldw %0, %%sp"::"o" (sp));
|
|
if (!lwpSave(*cpp))
|
|
lwpRestore(LwpCurrent->context);
|
|
lwpEntryPoint();
|
|
}
|
|
}
|
|
|
|
int
|
|
lwpSave(jmp_buf jb)
|
|
{
|
|
/* save stack pointer and return program counter */
|
|
asm("stw %sp, 4(%arg0)");
|
|
asm("stw %rp, 8(%arg0)");
|
|
|
|
/* save "callee save" registers */
|
|
asm("stw %r3, 12(%arg0)");
|
|
asm("stw %r4, 16(%arg0)");
|
|
asm("stw %r5, 20(%arg0)");
|
|
asm("stw %r6, 24(%arg0)");
|
|
asm("stw %r7, 28(%arg0)");
|
|
asm("stw %r8, 32(%arg0)");
|
|
asm("stw %r9, 36(%arg0)");
|
|
asm("stw %r10, 40(%arg0)");
|
|
asm("stw %r11, 44(%arg0)");
|
|
asm("stw %r12, 48(%arg0)");
|
|
asm("stw %r13, 52(%arg0)");
|
|
asm("stw %r14, 56(%arg0)");
|
|
asm("stw %r15, 60(%arg0)");
|
|
asm("stw %r16, 64(%arg0)");
|
|
asm("stw %r17, 68(%arg0)");
|
|
asm("stw %r18, 72(%arg0)");
|
|
|
|
/* save "callee save" space register */
|
|
asm volatile ("mfsp %sr3, %r1");
|
|
asm("stw %r1, 0(%arg0)");
|
|
|
|
/* indicate "true return" from saved() */
|
|
asm("ldi 0, %ret0");
|
|
|
|
asm(".LABEL _comefrom_");
|
|
}
|
|
|
|
void
|
|
lwpRestore(jmp_buf jb)
|
|
{
|
|
/* restore stack pointer and program counter */
|
|
asm volatile ("ldw 4(%arg0), %sp");
|
|
asm volatile ("ldw 8(%arg0), %rp");
|
|
|
|
/* restore "callee save" space register */
|
|
asm volatile ("ldw 0(%arg0), %r1");
|
|
asm volatile ("mtsp %r1, %sr3");
|
|
|
|
/* restore "callee save" registers */
|
|
asm volatile ("ldw 12(%arg0), %r3");
|
|
asm volatile ("ldw 16(%arg0), %r4");
|
|
asm volatile ("ldw 20(%arg0), %r5");
|
|
asm volatile ("ldw 24(%arg0), %r6");
|
|
asm volatile ("ldw 28(%arg0), %r7");
|
|
asm volatile ("ldw 32(%arg0), %r8");
|
|
asm volatile ("ldw 36(%arg0), %r9");
|
|
asm volatile ("ldw 40(%arg0), %r10");
|
|
asm volatile ("ldw 44(%arg0), %r11");
|
|
asm volatile ("ldw 48(%arg0), %r12");
|
|
asm volatile ("ldw 52(%arg0), %r13");
|
|
asm volatile ("ldw 56(%arg0), %r14");
|
|
asm volatile ("ldw 60(%arg0), %r15");
|
|
asm volatile ("ldw 64(%arg0), %r16");
|
|
asm volatile ("ldw 68(%arg0), %r17");
|
|
asm volatile ("ldw 72(%arg0), %r18");
|
|
|
|
/* warp to saved() to unwind the frame correctly */
|
|
asm volatile ("bl _comefrom_, %r0");
|
|
asm volatile ("ldi 1, %ret0");
|
|
}
|
|
|
|
#elif defined(FBSD)
|
|
|
|
void
|
|
lwpInitContext(struct lwpProc *newp, void *sp)
|
|
{
|
|
setjmp(newp->context);
|
|
newp->context->_jb[2] = (int)sp;
|
|
newp->context->_jb[3] = (int)sp;
|
|
newp->context->_jb[0] = (int)lwpEntryPoint;
|
|
}
|
|
|
|
#elif defined(__linux__)
|
|
|
|
void
|
|
lwpInitContext(struct lwpProc *newp, void *sp)
|
|
{
|
|
#if defined(__GLIBC__) && (__GLIBC__ >= 2)
|
|
#if defined(__PPC__)
|
|
newp->context->__jmpbuf[JB_GPR1] = (int)sp;
|
|
newp->context->__jmpbuf[JB_LR] = (int)lwpEntryPoint;
|
|
#else
|
|
newp->context->__jmpbuf[JB_SP] = (int)sp;
|
|
newp->context->__jmpbuf[JB_BP] = (int)sp;
|
|
newp->context->__jmpbuf[JB_PC] = (int)lwpEntryPoint;
|
|
#endif
|
|
#else
|
|
newp->context->__sp = sp;
|
|
newp->context->__bp = sp;
|
|
newp->context->__pc = (void *)lwpEntryPoint;
|
|
#endif
|
|
}
|
|
|
|
#elif defined(SUN3)
|
|
|
|
void
|
|
lwpInitContext(struct lwpProc *newp, void *sp)
|
|
{
|
|
newp->context[2] = (int)sp;
|
|
newp->context[3] = (int)lwpEntryPoint;
|
|
}
|
|
|
|
#elif defined(SUN4)
|
|
|
|
void
|
|
lwpInitContext(struct lwpProc *newp, void *sp)
|
|
{
|
|
static jmp_buf *cpp;
|
|
|
|
memset(newp->context, 0, sizeof(newp->context));
|
|
newp->context[0] = (int)sp;
|
|
/* preserve cpp for new context */
|
|
cpp = (jmp_buf *) & newp->context;
|
|
if (!_setjmp(LwpCurrent->context)) {
|
|
/* create new context */
|
|
/* flush registers */
|
|
asm("ta 0x03");
|
|
/* %o0 <- newp */
|
|
asm("ld [%fp+0x44], %o0");
|
|
/* %o1 <- newp->context[0] */
|
|
asm("ld [%o0], %o1");
|
|
/* create min frame on new stack */
|
|
asm("save %o1,-96, %sp");
|
|
if (!_setjmp(*cpp))
|
|
_longjmp(LwpCurrent->context, 1);
|
|
lwpEntryPoint();
|
|
}
|
|
}
|
|
|
|
#elif defined(ALPHA)
|
|
|
|
#include <c_asm.h>
|
|
|
|
void
|
|
lwpInitContext(struct lwpProc *newp, void *sp)
|
|
{
|
|
extern long *_gp;
|
|
|
|
/* register values obtained from setjmp.h */
|
|
_setjmp(newp->context);
|
|
newp->context[2] = (long)lwpEntryPoint; /* program counter */
|
|
newp->context[30] = (long)lwpEntryPoint; /* return address */
|
|
newp->context[31] = (long)lwpEntryPoint; /* fake program value (!) */
|
|
newp->context[34] = (long)sp; /* stack pointer */
|
|
}
|
|
|
|
int
|
|
lwpSave(jmp_buf jb)
|
|
{
|
|
return _setjmp(jb);
|
|
}
|
|
|
|
void
|
|
lwpRestore(jmp_buf jb)
|
|
{
|
|
/* resume, but get the pv from the jmp_buf */
|
|
asm("ldq %pv, 248(%a0)");
|
|
asm("stq %a0, 16(%sp)");
|
|
/* generates a warning, but functions just fine */
|
|
asm("bsr %ra, __longjump_resume");
|
|
}
|
|
|
|
#elif defined(AIX32)
|
|
/* Code is in .s files, as compiler doesn't grok asm */
|
|
#endif
|
|
|
|
#endif
|