2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23 * related information and legal notices. It is expected that any future
24 * projects/authors will amend these files as needed.
28 * arch.c: architecture-dependant process context code
30 * Known contributors to this file:
32 * Steve McClure, 1994-2000
38 #if defined(_EMPTH_LWP)
41 * Implement machine-dependent functions lwpInitContext(), lwpSave(),
44 * If lwpSave() and lwpRestore() are #def'd to setjmp() and longjmp(),
45 * then lwpInitContext() needs to set up the jmp_buf for a longjmp(),
46 * similar to setjmp(). To figure that out for another machine, check
47 * their source or reverse engineer.
53 * Alternate aproach using setcontext and getcontext instead of setjmp and
54 * longjump. This should work on any SVr4 machine independant of
55 * architecture. Unfortunately some changes are still nessesary in lwp.c.
60 lwpInitContext(struct lwpProc *newp, stack_t *spp)
62 getcontext(&newp->context);
63 newp->context.uc_stack.ss_sp = spp->ss_sp;
64 newp->context.uc_stack.ss_size = spp->ss_size;
65 newp->context.uc_link = NULL;
66 makecontext(&newp->context, lwpEntryPoint, 0);
71 static struct lwpProc *tempcontext;
72 static struct lwpProc *initcontext = NULL;
73 static int startpoint;
81 startpoint = (void *)&x;
82 if (!setjmp(initcontext->context))
83 longjmp(tempcontext->context, 1);
85 if (!setjmp(tempcontext->context))
86 longjmp(LwpCurrent->context, 1);
92 lwpInitContext(struct lwpProc *newp, void *sp)
94 struct lwpProc holder;
97 if (initcontext == NULL) {
98 initcontext = malloc(sizeof(struct lwpProc));
99 tempcontext = &holder;
100 if (!setjmp(tempcontext->context))
105 endpoint = &endpoint;
106 if (endpoint < startpoint) {
107 if (!setjmp(LwpCurrent->context))
108 longjmp(initcontext->context, 1);
110 LwpCurrent->size = endpoint - startpoint;
111 LwpCurrent->sbtm = realloc(LwpCurrent->sbtm, LwpCurrent->size);
112 memcpy(LwpCurrent->sbtm, startpoint, LwpCurrent->size);
113 if (!setjmp(LwpCurrent->context))
114 longjmp(initcontext->context, 1);
115 memcpy(startpoint, LwpCurrent->sbtm, LwpCurrent->size);
124 endpoint = &endpoint;
125 if (initcontext == NULL || endpoint < startpoint)
126 return setjmp(jb, 1);
128 LwpCurrent->size = endpoint - startpoint;
129 LwpCurrent->sbtm = realloc(LwpCurrent->sbtm, LwpCurrent->size);
130 memcpy(LwpCurrent->sbtm, startpoint, LwpCurrent->size);
132 memcpy(startpoint, LwpCurrent->sbtm, LwpCurrent->size);
141 lwpInitContext(volatile struct lwpProc *volatile newp, void *sp)
145 if (!lwpSave(LwpCurrent->context)) {
146 cpp = (jmp_buf *) & newp->context;
147 asm volatile ("ldw %0, %%sp"::"o" (sp));
149 lwpRestore(LwpCurrent->context);
157 /* save stack pointer and return program counter */
158 asm("stw %sp, 4(%arg0)");
159 asm("stw %rp, 8(%arg0)");
161 /* save "callee save" registers */
162 asm("stw %r3, 12(%arg0)");
163 asm("stw %r4, 16(%arg0)");
164 asm("stw %r5, 20(%arg0)");
165 asm("stw %r6, 24(%arg0)");
166 asm("stw %r7, 28(%arg0)");
167 asm("stw %r8, 32(%arg0)");
168 asm("stw %r9, 36(%arg0)");
169 asm("stw %r10, 40(%arg0)");
170 asm("stw %r11, 44(%arg0)");
171 asm("stw %r12, 48(%arg0)");
172 asm("stw %r13, 52(%arg0)");
173 asm("stw %r14, 56(%arg0)");
174 asm("stw %r15, 60(%arg0)");
175 asm("stw %r16, 64(%arg0)");
176 asm("stw %r17, 68(%arg0)");
177 asm("stw %r18, 72(%arg0)");
179 /* save "callee save" space register */
180 asm volatile ("mfsp %sr3, %r1");
181 asm("stw %r1, 0(%arg0)");
183 /* indicate "true return" from saved() */
186 asm(".LABEL _comefrom_");
190 lwpRestore(jmp_buf jb)
192 /* restore stack pointer and program counter */
193 asm volatile ("ldw 4(%arg0), %sp");
194 asm volatile ("ldw 8(%arg0), %rp");
196 /* restore "callee save" space register */
197 asm volatile ("ldw 0(%arg0), %r1");
198 asm volatile ("mtsp %r1, %sr3");
200 /* restore "callee save" registers */
201 asm volatile ("ldw 12(%arg0), %r3");
202 asm volatile ("ldw 16(%arg0), %r4");
203 asm volatile ("ldw 20(%arg0), %r5");
204 asm volatile ("ldw 24(%arg0), %r6");
205 asm volatile ("ldw 28(%arg0), %r7");
206 asm volatile ("ldw 32(%arg0), %r8");
207 asm volatile ("ldw 36(%arg0), %r9");
208 asm volatile ("ldw 40(%arg0), %r10");
209 asm volatile ("ldw 44(%arg0), %r11");
210 asm volatile ("ldw 48(%arg0), %r12");
211 asm volatile ("ldw 52(%arg0), %r13");
212 asm volatile ("ldw 56(%arg0), %r14");
213 asm volatile ("ldw 60(%arg0), %r15");
214 asm volatile ("ldw 64(%arg0), %r16");
215 asm volatile ("ldw 68(%arg0), %r17");
216 asm volatile ("ldw 72(%arg0), %r18");
218 /* warp to saved() to unwind the frame correctly */
219 asm volatile ("bl _comefrom_, %r0");
220 asm volatile ("ldi 1, %ret0");
226 lwpInitContext(struct lwpProc *newp, void *sp)
228 setjmp(newp->context);
229 newp->context->_jb[2] = (int)sp;
230 newp->context->_jb[3] = (int)sp;
231 newp->context->_jb[0] = (int)lwpEntryPoint;
234 #elif defined(__linux__)
237 lwpInitContext(struct lwpProc *newp, void *sp)
239 #if defined(__GLIBC__) && (__GLIBC__ >= 2)
241 newp->context->__jmpbuf[JB_GPR1] = (int)sp;
242 newp->context->__jmpbuf[JB_LR] = (int)lwpEntryPoint;
244 newp->context->__jmpbuf[JB_SP] = (int)sp;
245 newp->context->__jmpbuf[JB_BP] = (int)sp;
246 newp->context->__jmpbuf[JB_PC] = (int)lwpEntryPoint;
249 newp->context->__sp = sp;
250 newp->context->__bp = sp;
251 newp->context->__pc = (void *)lwpEntryPoint;
258 lwpInitContext(struct lwpProc *newp, void *sp)
260 newp->context[2] = (int)sp;
261 newp->context[3] = (int)lwpEntryPoint;
267 lwpInitContext(struct lwpProc *newp, void *sp)
271 memset(newp->context, 0, sizeof(newp->context));
272 newp->context[0] = (int)sp;
273 /* preserve cpp for new context */
274 cpp = (jmp_buf *) & newp->context;
275 if (!_setjmp(LwpCurrent->context)) {
276 /* create new context */
277 /* flush registers */
280 asm("ld [%fp+0x44], %o0");
281 /* %o1 <- newp->context[0] */
282 asm("ld [%o0], %o1");
283 /* create min frame on new stack */
284 asm("save %o1,-96, %sp");
286 _longjmp(LwpCurrent->context, 1);
296 lwpInitContext(struct lwpProc *newp, void *sp)
300 /* register values obtained from setjmp.h */
301 _setjmp(newp->context);
302 newp->context[2] = (long)lwpEntryPoint; /* program counter */
303 newp->context[30] = (long)lwpEntryPoint; /* return address */
304 newp->context[31] = (long)lwpEntryPoint; /* fake program value (!) */
305 newp->context[34] = (long)sp; /* stack pointer */
315 lwpRestore(jmp_buf jb)
317 /* resume, but get the pv from the jmp_buf */
318 asm("ldq %pv, 248(%a0)");
319 asm("stq %a0, 16(%sp)");
320 /* generates a warning, but functions just fine */
321 asm("bsr %ra, __longjump_resume");
325 /* Code is in .s files, as compiler doesn't grok asm */