]> git.pond.sub.org Git - empserver/blob - src/lib/lwp/arch.c
Import of Empire 4.2.12
[empserver] / src / lib / lwp / arch.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
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.
10  *
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.
15  *
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
19  *
20  *  ---
21  *
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.
25  *
26  *  ---
27  *
28  *  arch.c: architecture-dependant process context code
29  * 
30  *  Known contributors to this file:
31  *     Dave Pare, 1994
32  *     Steve McClure, 1994-2000
33  */
34
35 #include "prototypes.h"
36
37 #if defined(_EMPTH_LWP)
38
39 #if (!defined(AIX32))
40
41 #include "lwp.h"
42
43 #include "lwpint.h"
44
45 #if defined(hpc)
46
47 static struct lwpProc *tempcontext;
48 struct lwpProc *initcontext=NULL;
49 int startpoint;
50
51 startcontext()
52 {
53         int space[10000];
54         int x;
55
56         startpoint = (void *) &x;
57         if (!setjmp(initcontext->context)) longjmp(tempcontext->context,1);
58
59         if (!setjmp(tempcontext->context)) longjmp(LwpCurrent->context,1);
60
61         lwpEntryPoint();
62 }
63
64 void lwpInitContext(newp, sp)
65         struct lwpProc *newp;
66         void            *sp;
67 {
68         struct lwpProc holder;
69         int endpoint;
70
71         if (initcontext == NULL) {
72                 initcontext = (struct lwpProc *) malloc (sizeof(struct lwpProc));
73                 tempcontext = &holder;
74                 if (!setjmp(tempcontext->context)) startcontext();
75         }
76
77         tempcontext = newp;
78         endpoint = &endpoint;
79         if (endpoint < startpoint) {
80                 if (!setjmp(LwpCurrent->context)) longjmp(initcontext->context,1);
81         } else {
82                 LwpCurrent->size = endpoint - startpoint;
83                 LwpCurrent->sbtm = realloc(LwpCurrent->sbtm, LwpCurrent->size);
84                 memcpy(LwpCurrent->sbtm, startpoint, LwpCurrent->size);
85                 if (!setjmp(LwpCurrent->context)) longjmp(initcontext->context,1);
86                 memcpy(startpoint, LwpCurrent->sbtm, LwpCurrent->size);
87         }
88 }
89
90 #elif defined(hpux)
91
92 void lwpInitContext(newp, sp)
93         volatile struct lwpProc *volatile newp;
94         void    *sp;
95 {
96     static jmp_buf *cpp;
97     extern struct lwpProc *LwpCurrent;
98
99     if (!lwpSave(LwpCurrent->context)) {
100         cpp = (jmp_buf *)&newp->context;
101         asm volatile ("ldw      %0, %%sp": : "o" (sp));
102         if (!lwpSave(*cpp))
103             lwpRestore(LwpCurrent->context);
104         lwpEntryPoint();
105     }
106 }
107
108 int lwpSave(jb)
109         jmp_buf jb;
110 {
111         /* save stack pointer and return program counter */
112         asm ("stw       %sp, 4(%arg0)");
113         asm ("stw       %rp, 8(%arg0)");
114
115         /* save "callee save" registers */
116         asm ("stw       %r3, 12(%arg0)");
117         asm ("stw       %r4, 16(%arg0)");
118         asm ("stw       %r5, 20(%arg0)");
119         asm ("stw       %r6, 24(%arg0)");
120         asm ("stw       %r7, 28(%arg0)");
121         asm ("stw       %r8, 32(%arg0)");
122         asm ("stw       %r9, 36(%arg0)");
123         asm ("stw       %r10, 40(%arg0)");
124         asm ("stw       %r11, 44(%arg0)");
125         asm ("stw       %r12, 48(%arg0)");
126         asm ("stw       %r13, 52(%arg0)");
127         asm ("stw       %r14, 56(%arg0)");
128         asm ("stw       %r15, 60(%arg0)");
129         asm ("stw       %r16, 64(%arg0)");
130         asm ("stw       %r17, 68(%arg0)");
131         asm ("stw       %r18, 72(%arg0)");
132
133         /* save "callee save" space register */
134         asm volatile ("mfsp     %sr3, %r1");
135         asm ("stw       %r1, 0(%arg0)");
136
137         /* indicate "true return" from saved() */
138         asm ("ldi       0, %ret0");
139
140         asm (".LABEL _comefrom_");
141 }
142
143 void
144 lwpRestore(jb)
145         jmp_buf jb;
146 {
147         /* restore stack pointer and program counter */
148         asm volatile ("ldw      4(%arg0), %sp");
149         asm volatile ("ldw      8(%arg0), %rp");
150
151         /* restore "callee save" space register */
152         asm volatile ("ldw      0(%arg0), %r1");
153         asm volatile ("mtsp     %r1, %sr3");
154
155         /* restore "callee save" registers */
156         asm volatile ("ldw      12(%arg0), %r3");
157         asm volatile ("ldw      16(%arg0), %r4");
158         asm volatile ("ldw      20(%arg0), %r5");
159         asm volatile ("ldw      24(%arg0), %r6");
160         asm volatile ("ldw      28(%arg0), %r7");
161         asm volatile ("ldw      32(%arg0), %r8");
162         asm volatile ("ldw      36(%arg0), %r9");
163         asm volatile ("ldw      40(%arg0), %r10");
164         asm volatile ("ldw      44(%arg0), %r11");
165         asm volatile ("ldw      48(%arg0), %r12");
166         asm volatile ("ldw      52(%arg0), %r13");
167         asm volatile ("ldw      56(%arg0), %r14");
168         asm volatile ("ldw      60(%arg0), %r15");
169         asm volatile ("ldw      64(%arg0), %r16");
170         asm volatile ("ldw      68(%arg0), %r17");
171         asm volatile ("ldw      72(%arg0), %r18");
172
173         /* warp to saved() to unwind the frame correctly */
174         asm volatile ("bl       _comefrom_, %r0");      
175         asm volatile ("ldi      1, %ret0");
176 }
177
178 #elif defined(BSD386)
179 void lwpInitContext(newp, sp)
180         struct lwpProc *newp;
181         void *sp;
182 {
183         newp->context[2] = (int)sp;
184         newp->context[0] = (int)lwpEntryPoint;
185 }
186
187 #elif defined(FBSD)
188
189 void lwpInitContext(newp, sp)
190         struct lwpProc *newp;
191         void *sp;
192 {
193         setjmp (newp->context);
194         newp->context->_jb[2] = (int)sp;
195         newp->context->_jb[3] = (int)sp;
196         newp->context->_jb[0] = (int)lwpEntryPoint;
197 }
198
199 #elif defined(__linux__)
200
201 void lwpInitContext(newp, sp)
202         struct lwpProc *newp;
203         void    *sp;
204 {
205 #if defined(__GLIBC__) && (__GLIBC__ >= 2)
206 #if defined(__PPC__)
207       newp->context->__jmpbuf[JB_GPR1] = (int) sp;
208       newp->context->__jmpbuf[JB_LR] = (int) lwpEntryPoint;
209 #else
210         newp->context->__jmpbuf[JB_SP] = (int) sp;
211         newp->context->__jmpbuf[JB_BP] = (int) sp;
212         newp->context->__jmpbuf[JB_PC] = (int) lwpEntryPoint;
213 #endif
214 #else
215         newp->context->__sp = sp;
216         newp->context->__bp = sp;
217         newp->context->__pc = (void *)lwpEntryPoint;
218 #endif
219 }
220
221 #elif defined(SUN3)
222
223 void lwpInitContext(newp, sp)
224         struct lwpProc *newp;
225         void    *sp;
226 {
227         newp->context[2] = (int)sp;
228         newp->context[3] = (int)lwpEntryPoint;
229 }
230
231 #elif defined(__vax)
232
233 #include <stdio.h>
234
235 void lwpInitContext(newp, stack)
236         struct lwpProc *newp;
237         void    *stack;
238 {
239     int *sp = (int*)stack;
240     int *fp = 0;
241
242     /* Build root frame on new stack for lwpEntryPoint */
243     *--sp = 0;                  /* pc */
244     *--sp = (int)fp;            /* fp */
245     *--sp = 0;                  /* ap */
246     *--sp = 0;                  /* psw  */
247     *--sp = 0;                  /* condition handler */
248     fp = sp;
249
250     /* Build stack frame to return from. */
251     *--sp = (int)lwpEntryPoint+2;/* pc */
252     *--sp = (int)fp;            /* fp */
253     *--sp = 0;                  /* ap */
254     *--sp = 0;                  /* psw  */
255     *--sp = 0;                  /* condition handler */
256     fp = sp;
257
258     /* Fill in the context */
259     /* Note: This is *not* how libc fills out jump buffers. */
260     newp->context[0] = 0;       /* r6 */
261     newp->context[1] = 0;
262     newp->context[2] = 0;
263     newp->context[3] = 0;
264     newp->context[4] = 0;
265     newp->context[5] = 0;       /* r11 */
266     newp->context[6] = 0;       /* ap */
267     newp->context[7] = (int)fp; /* fp */
268     return;
269 }
270
271 int lwpSave(jb)
272     jmp_buf jb;
273 {
274     asm("movl 4(ap), r0");      /* r0 = &jb */
275     asm("movl r6, (r0)");       /* jb[0] = r6 */
276     asm("movl r7, 4(r0)");
277     asm("movl r8, 8(r0)");
278     asm("movl r9, 12(r0)");
279     asm("movl r10, 16(r0)");
280     asm("movl r11, 20(r0)");
281     asm("movl ap, 24(r0)");
282     asm("movl fp, 28(r0)");     /* jb[7] = fp */
283     return 0;
284 }
285
286 void lwpRestore(jb)
287     jmp_buf jb;
288 {
289     asm("movl 4(ap), r0");      /* r0 = &jb */
290     asm("movl (r0), r6");       /* r6 = jb[0] */
291     asm("movl 4(r0), r7");
292     asm("movl 8(r0), r8");
293     asm("movl 12(r0), r9");
294     asm("movl 16(r0), r10");
295     asm("movl 20(r0), r11");
296     asm("movl 24(r0), ap");
297     asm("movl 28(r0), fp");     /* fp = jb[7] */
298     asm("movl $1, r0");         /* faked return 1 from lwpSave() */
299     asm("ret");
300     return;
301 }
302
303
304 #elif defined(SUN4)
305
306 void lwpInitContext(newp, sp)
307         struct lwpProc *newp;
308         void            *sp;
309 {
310         static jmp_buf *cpp;
311         extern struct lwpProc *LwpCurrent;
312
313         bzero(newp->context, sizeof(newp->context));
314         newp->context[0] = (int)sp;
315         /* preserve cpp for new context */
316         cpp = (jmp_buf *)&newp->context;
317         if (!_setjmp(LwpCurrent->context)) {
318                 /* create new context */                
319                 /* flush registers */
320                 asm ("ta        0x03");
321                 /* %o0 <- newp */
322                 asm ("ld        [%fp+0x44], %o0");
323                 /* %o1 <- newp->context[0] */
324                 asm ("ld        [%o0], %o1");
325                 /* create min frame on new stack */
326                 asm ("save      %o1,-96, %sp");
327                 if (!_setjmp(*cpp))
328                         _longjmp(LwpCurrent->context, 1);
329                 lwpEntryPoint();
330         }
331 }
332
333 #elif defined(__USLC__) && defined(i386)
334
335 /* USL/Unixware on an Intel 386/486/... processor.
336  * Tested on Unixware v1.1.2, based on SYSV R4.2
337  */
338
339 /* As per normal empire documentation, there is none.
340  *
341  * But, what we are attempting to do here is set up a longjump
342  * context buffer so that the lwpEntryPoint is called when
343  * the thread starts.
344  *
345  * I.E., what a setjmp/longjmp call set would do.
346  *
347  * How to figure this out?  Well, without the setjmp code, you
348  * need to reverse engineer it by printing out the context buffer
349  * and the processor registers, and mapping which ones need
350  * to be set.
351  *
352  * Alternatively, you can single instruction step through the longjmp
353  * function, and figure out the offsets that it uses.
354  *
355  * Using offsets in bytes,
356  * context + 0x04 [1] -> esi  (general purpose reg)
357  * context + 0x08 [2] -> edi  (general purpose reg)
358  * context + 0x0C [3] -> ebp  (general purpose or parameter passing)
359  * context + 0x10 [4] -> esp  (stack)
360  * context + 0x14 [5] -> jump location for return
361  */
362
363 void lwpInitContext(newp, sp)
364         struct lwpProc *newp;
365         void    *sp;
366 {
367         newp->context[4] = (int)sp;
368         newp->context[5] = (int)lwpEntryPoint;
369 }
370
371 #elif defined UCONTEXT
372
373 /*
374  * Alternate aproach using setcontext en getcontext in stead of setjmp and
375  * longjump. This should work on any SVr4 machine independant of
376  * architecture. Unfortunaltely some changes are still nessesary in lwp.c.
377  * Tested on IRIX 5.3
378  */ 
379
380 void lwpInitContext(newp, spp)
381       struct lwpProc *newp;
382       stack_t *spp;
383 {
384       getcontext (&(newp->context));
385       newp->context.uc_stack.ss_sp = spp->ss_sp;
386       newp->context.uc_stack.ss_size = spp->ss_size;
387       makecontext (&(newp->context), lwpEntryPoint, 0);
388 }
389
390 #elif defined(ALPHA)
391
392 #include <c_asm.h>
393
394 void lwpInitContext(newp, sp)
395         struct lwpProc *newp;
396         void    *sp;
397 {
398         extern long *_gp;
399
400         /* register values obtained from setjmp.h */
401         _setjmp(newp->context);
402         newp->context[2] = (long)lwpEntryPoint; /* program counter */
403         newp->context[30] = (long)lwpEntryPoint; /* return address */
404         newp->context[31] = (long)lwpEntryPoint; /* fake program value (!) */
405         newp->context[34] = (long)sp;           /* stack pointer */
406 }
407
408 int lwpSave(jb)
409         jmp_buf jb;
410 {
411         return _setjmp(jb);
412 }
413
414 void lwpRestore(jb)
415         jmp_buf jb;
416 {
417         /* resume, but get the pv from the jmp_buf */
418         asm("ldq        %pv, 248(%a0)");
419         asm("stq        %a0, 16(%sp)");
420         /* generates a warning, but functions just fine */
421         asm("bsr        %ra, __longjump_resume");
422 }
423
424 #endif
425
426 #endif
427
428 #endif