1f355c94e92dbe99471ed612b5bc0e8d1b9aa611
[openafs.git] / src / lwp / process.s
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #define IGNORE_STDS_H   1
11 /*#ifndef AFS_DJGPP_ENV*/
12 #include <afs/param.h>
13 /*#endif /* AFS_DJGPP_ENV */
14
15 #if defined(RIOS)
16
17 /*                 I don't know if we have to save the TOC (R2) or not...
18  *                 Note that stack-frame is supposed to be aligned on 
19  *                 a double-word boundary.
20  *                 For details about RIOS calling conventions
21  *                 see the Assembler manual and /usr/include/sys/asdef.s
22  */
23
24
25 /*
26  * savecontext(f, area1, newsp)
27  *     int (*f)(); struct savearea *area1; char *newsp;
28  */
29         .set    topstack, 0
30         .set    cr0, 0
31         .set    toc, 2
32         .set    r0, 0
33         .set    r1, 1
34         .set    r2, 2
35         .set    r3, 3
36         .set    r4, 4
37         .set    r5, 5
38         .set    r6, 6
39         .set    r7, 7
40         .set    r12, 12
41         .set    a_f, r3
42         .set    a_area1, r4
43         .set    a_newsp, r5
44
45         .set    argarea,  32
46         .set    linkarea, 24
47         .set    nfprs,    18
48         .set    ngprs,    20
49         .set    szdsa,    8*nfprs+4*ngprs+linkarea+argarea
50
51         .csect .savecontext[PR]
52         .globl .savecontext[PR]
53
54         mflr    r0                      # save link register
55                 
56 /*
57  *  save floating point registers.  Interleave some other stuff for
58  *  timing reasons.  Set up conditions and registers for branches
59  *  early, so that processor can prefetch instructions.
60  */
61         stfd  14, -144(1)
62         stfd  15, -136(1)
63
64         mfcr    r12                     # save CR
65
66         stfd  16, -128(1)
67         stfd  17, -120(1)
68
69         l       11, 0(a_f)              # r11 <- *(a_f)
70
71         stfd  18, -112(1)
72         stfd  19, -104(1)
73
74         cmpi    cr0, a_newsp, 0         # cr0 <- (a_newsp :: 0)
75
76         stfd  20, -96(1)
77         stfd  21, -88(1)
78         stfd  22, -80(1)
79
80         mtlr    11                      # set up lr early so prefetch works
81
82         stfd  23, -72(1)
83         stfd  24, -64(1)
84         stfd  25, -56(1)
85
86         st      r0, 8(r1)               # save return addr
87
88         stfd  26, -48(1)
89         stfd  27, -40(1)
90         stfd  28, -32(1)
91
92         st      12, 4(r1)               # save CR
93
94         stfd  29, -24(1)
95         stfd  30, -16(1)
96         stfd  31, -8(1)
97
98 /*
99  *  save general-purpose registers
100  */
101         stm     12, -8*nfprs-4*ngprs(r1)# save the general-purpose regs
102         stu     r1, -szdsa(r1)          # dec SP and save back chain
103
104         l       r7,  PRE_Block.S(toc)   # r7 <- &PRE_Block
105         cal     r6, 1(r0)               # r6 <- #1
106         stb     r6, 0(r7)               # r6 -> PRE_Block
107
108         st      r1, topstack(a_area1)   # save old SP
109         
110         beq    L1                       # if (a_newsp == 0) goto L1
111
112         mr      r1, r5                  # r1 <- a_newsp -- load new SP
113
114 L1:     brl                             # pc <- lr      -- (*a_f)()
115
116 /*
117  * returnto(area2)   This is a little jumbled, I tried to interleave 
118  * memory accesses with simple instructions for speed, and I tried to 
119  * set up the link register and condition register reasonably early
120  * so that processor instruction prefetching might help us out a little.
121  */
122         .set    a_area2, r3
123
124         .csect  .returnto[PR]
125         .globl  .returnto[PR]
126
127         l       r1, topstack(a_area2)   # r1 <- a_area2->topstack
128         cal     r1,  szdsa(r1)          # pop off frame
129         l       r7, PRE_Block.S(toc)    # r7 <- &PRE_Block
130
131         l       8, 8(1)                 # restore lr
132         mtlr    8                       # do it early so prefetch works
133
134         lm      12,  -8*nfprs-4*ngprs(r1)
135         cal     r6, 0(r0)               # r6 <- #0
136         mtcrf   0x38, 12                # put back cr
137         stb     r6, 0(r7)               # r6 -> PRE_Block
138
139 /*
140  * restore FPRs here!
141  */
142         lfd  14, -144(1)
143         lfd  15, -136(1)
144         lfd  16, -128(1)
145         lfd  17, -120(1)
146         lfd  18, -112(1)
147         lfd  19, -104(1)
148         lfd  20, -96(1)
149         lfd  21, -88(1)
150         lfd  22, -80(1)
151         lfd  23, -72(1)
152         lfd  24, -64(1)
153         lfd  25, -56(1)
154         lfd  26, -48(1)
155         lfd  27, -40(1)
156         lfd  28, -32(1)
157         lfd  29, -24(1)
158         lfd  30, -16(1)
159         lfd  31, -8(1)
160
161         brl                             # pc <- lr      -- return
162
163         .toc
164
165 PRE_Block.S:
166         .tc     PRE_Block[tc], PRE_Block[ua]
167         .extern PRE_Block[ua]
168
169 #endif  /* RIOS */
170 #if defined(AFS_S390_LINUX20_ENV)
171       /* Linux for S/390 (31 bit)
172        *
173        * Written by Neale Ferguson <Neale.Ferguson@SoftwareAG-usa.com>
174        *
175        *  additional munging by Adam Thornton <adam@sinenomine.net>
176        */
177               .file   "process.s"
178
179               .globl savecontext
180               .type  savecontext,%function
181       /*
182        * savecontext(f, area1, newsp)
183        *      int (*f)();    struct savearea *area1; char *newsp;
184        * f     - r2
185        * area1 - r3
186        * newsp - r4
187        */
188
189        /*
190         * struct savearea {
191         *      char    *topstack;
192         * }
193         */
194
195 P_PRE:                    .long   PRE_Block
196 P_ABORT:                      .long   abort
197
198 savecontext:
199               stm     %r6,%r15,24(%r15)       /* Save our registers */
200               lr      %r1,%r15
201               ahi     %r15,-96                /* Move out of harm's way */
202               st      %r1,0(%r15)
203               bras    %r5,.L0                 /* Get A(A(PRE_Block)) */
204               .long   PRE_Block
205       .L0:
206               l       %r5,0(%r5)              /* Get A(PRE_Block) */
207               mvi     3(%r5),1                /* Set it */
208               lr      %r6,%r3                 /* Get base of savearea */
209               st      %r15,0(%r3)             /* Save stack pointer */
210               ltr     %r4,%r4                 /* If new sp is 0 */
211               jz      .L1                     /* ... don't change sp */
212               lr      %r15,%r4                /* Set new stack pointer */
213       .L1:
214               br      %r2                     /* Call the routine */
215               /* Can't get here....*/
216
217               bras    %r5,.L2
218               .long   abort
219       .L2:
220               l      %r5,0(%r5)
221               balr    %r14,%r5
222
223       .savecontext_end:
224               .size   savecontext,.savecontext_end-savecontext
225
226       /*
227        * returnto(area2)
228        *      struct savearea *area2;
229        *
230        * area2 - r2
231        */
232         .globl  returnto
233         .type   returnto,%function
234 returnto:
235         l       %r15,0(%r2)             /* New frame, to get correct pointer*/
236         bras    %r5,.L3                         /* Get A(A(PRE_Block))
237       */
238                  .long          PRE_Block
239       .L3:
240               l       %r5,0(%r5)              /* Get A(PRE_Block) */
241               /*xc      0(4,%r5),0(%r5)         /* Clear it */
242               mvi     3(%r5),0                /* Clear it */ 
243               l       %r15,0(%r15)
244               lm      %r6,%r15,24(%r15)       /* Restore registers */
245               br      %r14                    /* Return */
246
247               /* Can't happen */
248               la      %r2,1234
249               bras    %r5,.L4
250                 .long          abort
251       .L4:
252               l       %r5,0(%r5)
253               basr    %r14,%r5
254       .returnto_end:
255               .size   returnto,.returnto_end-returnto
256 #endif /* AFS_S390_LINUX20_ENV */
257         
258 #ifdef mc68000
259 /*
260 #
261 #       Information Technology Center
262 #       Carnegie-Mellon University
263 #
264 #
265 */
266         .data
267
268 /*
269 #
270 #       Process assembly language assist for Suns.
271 #
272 */
273
274         .text
275         .even
276
277 /*
278 #
279 # struct savearea {
280 #       char    *topstack;
281 # }
282 #
283 */
284
285         .globl  _PRE_Block
286
287 topstack =      0
288
289 /* Stuff to allow saving/restoring registers */
290 nregs   =       13
291 regs    =       0x3ffe                  | d1-d7 & a0-a5
292
293 /*
294 # savecontext(f, area1, newsp)
295 #     int (*f)(); struct savearea *area1; char *newsp;
296 */
297
298 /* Stack offsets of arguments */
299 f       =       8
300 area1   =       12
301 newsp   =       16
302
303         .globl  _savecontext
304 _savecontext:
305         movb    #1,_PRE_Block           | Dont allow any interrupt finagling
306         link    a6,#-(nregs*4)          | Save frame pointer & ...
307                                         | ... allocate space for nregs registers
308 /* Save registers */
309         moveml  #regs,sp@
310
311         movl    a6@(area1),a0           | a0 = base of savearea
312         movl    sp,a0@(topstack)        | area->topstack = sp
313         movl    a6@(newsp),d0           | Get new sp
314         jeq     forw1                   | If newsp == 0, no stack switch
315         movl    d0,sp                   | Switch to new stack
316 forw1:
317         movl    a6@(f),a0               | a0 = f
318         jbsr    a0@                     | f()
319
320 /* It is impossible to be here, so abort() */
321
322         jbsr    _abort
323
324 /*
325 # returnto(area2)
326 #     struct savearea *area2;
327 */
328
329 /* Stack offset of argument */
330 area2   =       8
331
332         .globl _returnto
333 _returnto:
334         link    a6,#0
335         movl    a6@(area2),a0           | Base of savearea
336         movl    a0@(topstack),sp        | Restore sp
337 /* Restore registers */
338         moveml  sp@,#regs
339
340         addl    #(nregs*4),sp
341         movl    sp,a6                   | Argghh...be careful here
342         unlk    a6
343         clrb    _PRE_Block
344         rts                             | Return to previous process
345 #endif /* mc68000 */
346 #ifdef  sparc
347 #ifdef  AFS_SUN5_ENV
348 #define _ASM    1
349 #include        <sys/asm_linkage.h>
350 #include  <sys/trap.h>
351 #else
352 #ifdef AFS_XBSD_ENV
353 #include <machine/trap.h>
354 #define ST_FLUSH_WINDOWS ST_FLUSHWIN
355 #define MINFRAME 92
356 #define SA(x) (((x)+7)&~7)
357 #define STACK_ALIGN 8
358 #else /* SunOS 4: */
359 #include        <sun4/asm_linkage.h>
360 #include  <sun4/trap.h>
361 #endif
362 #endif
363         .data   
364 #ifdef  AFS_SUN5_ENV
365         .globl  PRE_Block
366 #else
367         .globl  _PRE_Block
368 #endif
369 topstack        = 0
370 globals = 4
371 /*
372 # savecontext(f, area1, newsp)
373 #     int (*f)(); struct savearea *area1; char *newsp;
374 */
375         .text
376 #ifdef  AFS_SUN5_ENV
377         .globl  savecontext
378 savecontext:
379 #else
380         .globl  _savecontext
381 _savecontext:
382 #endif
383         save    %sp, -SA(MINFRAME), %sp ! Get new window
384         ta      ST_FLUSH_WINDOWS                ! FLush all other active windows
385
386         /* The following 3 lines do the equivalent of: _PRE_Block = 1 */
387 #ifdef  AFS_SUN5_ENV
388         set     PRE_Block, %l0
389 #else
390         set     _PRE_Block, %l0
391 #endif
392         mov     1,%l1
393         stb     %l1, [%l0]
394
395         st      %fp,[%i1+topstack]              ! area1->topstack = sp
396         
397         st      %g1, [%i1 + globals + 0]                /* Save all globals just in case */
398         st      %g2, [%i1 + globals + 4]
399         st      %g3, [%i1 + globals + 8]
400         st      %g4, [%i1 + globals + 12]
401         st      %g5, [%i1 + globals + 16]
402         st      %g6, [%i1 + globals + 20]
403         st      %g7, [%i1 + globals + 24]
404         mov     %y, %g1
405         st      %g1, [%i1 + globals + 28]
406
407 #ifdef  save_allregs
408         st      %f0, [%i1 + globals + 32 + 0]           ! Save all floating point registers 
409         st      %f1, [%i1 + globals + 32 + 4]
410         st      %f2, [%i1 + globals + 32 + 8]
411         st      %f3, [%i1 + globals + 32 + 12]
412         st      %f4, [%i1 + globals + 32 + 16]
413         st      %f5, [%i1 + globals + 32 + 20]
414         st      %f6, [%i1 + globals + 32 + 24]
415         st      %f7, [%i1 + globals + 32 + 28]
416         st      %f8, [%i1 + globals + 64 + 0]
417         st      %f9, [%i1 + globals + 64 + 4]
418         st      %f10, [%i1 + globals + 64 + 8]
419         st      %f11, [%i1 + globals + 64 + 12]
420         st      %f12, [%i1 + globals + 64 + 16]
421         st      %f13, [%i1 + globals + 64 + 20]
422         st      %f14, [%i1 + globals + 64 + 24]
423         st      %f15, [%i1 + globals + 64 + 28]
424         st      %f16, [%i1 + globals + 64 + 32]
425         st      %f17, [%i1 + globals + 64 + 36]
426         st      %f18, [%i1 + globals + 64 + 40]
427         st      %f19, [%i1 + globals + 64 + 44]
428         st      %f20, [%i1 + globals + 64 + 48]
429         st      %f21, [%i1 + globals + 64 + 52]
430         st      %f22, [%i1 + globals + 64 + 56]
431         st      %f23, [%i1 + globals + 64 + 60]
432         st      %f24, [%i1 + globals + 64 + 64]
433         st      %f25, [%i1 + globals + 64 + 68]
434         st      %f26, [%i1 + globals + 64 + 72]
435         st      %f27, [%i1 + globals + 64 + 76]
436         st      %f28, [%i1 + globals + 64 + 80]
437         st      %f29, [%i1 + globals + 64 + 84]
438         st      %f30, [%i1 + globals + 64 + 88]
439         st      %f31, [%i1 + globals + 64 + 92]
440 #ifdef  notdef
441         mov     %fsr,%g1
442         st      %g1, [%i1 + globals + 64 + 96]
443         mov     %fq,%g1
444         st      %g1, [%i1 + globals + 64 + 100]
445 #endif
446
447         st      %c0, [%i1 + globals + 168 + 0]                  ! Save all coprocessor registers 
448         st      %c1, [%i1 + globals + 168 + 4]
449         st      %c2, [%i1 + globals + 168 + 8]
450         st      %c3, [%i1 + globals + 168 + 12]
451         st      %c4, [%i1 + globals + 168 + 16]
452         st      %c5, [%i1 + globals + 168 + 20]
453         st      %c6, [%i1 + globals + 168 + 24]
454         st      %c7, [%i1 + globals + 168 + 28]
455         st      %c8, [%i1 + globals + 200 + 0]
456         st      %c9, [%i1 + globals + 200 + 4]
457         st      %c10, [%i1 + globals + 200 + 8]
458         st      %c11, [%i1 + globals + 200 + 12]
459         st      %c12, [%i1 + globals + 200 + 16]
460         st      %c13, [%i1 + globals + 200 + 20]
461         st      %c14, [%i1 + globals + 200 + 24]
462         st      %c15, [%i1 + globals + 200 + 28]
463         st      %c16, [%i1 + globals + 200 + 32]
464         st      %c17, [%i1 + globals + 200 + 36]
465         st      %c18, [%i1 + globals + 200 + 40]
466         st      %c19, [%i1 + globals + 200 + 44]
467         st      %c20, [%i1 + globals + 200 + 48]
468         st      %c21, [%i1 + globals + 200 + 52]
469         st      %c22, [%i1 + globals + 200 + 56]
470         st      %c23, [%i1 + globals + 200 + 60]
471         st      %c24, [%i1 + globals + 200 + 64]
472         st      %c25, [%i1 + globals + 200 + 68]
473         st      %c26, [%i1 + globals + 200 + 72]
474         st      %c27, [%i1 + globals + 200 + 76]
475         st      %c28, [%i1 + globals + 200 + 80]
476         st      %c29, [%i1 + globals + 200 + 84]
477         st      %c30, [%i1 + globals + 200 + 88]
478         st      %c31, [%i1 + globals + 200 + 92]
479 #ifdef  notdef
480         mov     %csr,%g1
481         st      %g1, [%i1 + globals + 200 + 96]
482         mov     %cq,%g1
483         st      %g1, [%i1 + globals + 200 + 100]
484 #endif
485 #endif
486         cmp     %i2, 0
487         be,a    L1                              ! if (newsp == 0) no stack switch
488         nop
489 #ifdef  notdef
490         add     %i2, STACK_ALIGN - 1, %i2
491         and     %i2, ~(STACK_ALIGN - 1), %i2
492         sub     %i2, SA(MINFRAME), %fp
493         call    %i0
494         restore
495 #else
496         ! This used to compute a new stack frame base, write it into
497         ! FP, and restore to enter the new frame. But that left a window
498         ! in which FP could be written into the backing store for this
499         ! frame, to be tripped over later by returnto. So instead we do
500         ! the restore first, then modify SP to enter the new frame. We
501         ! can still refer to our argument as %02.
502         restore
503         add     %o2, STACK_ALIGN - 1, %o2
504         and     %o2, ~(STACK_ALIGN - 1), %o2    
505         call    %o0
506         sub     %o2, SA(MINFRAME), %sp
507 #endif  
508
509 L1:     call    %i0                     ! call f()
510         nop
511
512
513 ! returnto(area1)
514 !     struct savearea *area1;
515 #ifdef  AFS_SUN5_ENV
516         .globl returnto
517 returnto:
518 #else
519         .globl _returnto
520 _returnto:
521 #endif
522         ta      ST_FLUSH_WINDOWS                ! FLush all other active windows
523         ld      [%o0+topstack],%g1              ! sp = area1->topstack
524         sub     %g1, SA(MINFRAME), %fp  ! Adjust sp to the right place
525         sub     %fp, SA(MINFRAME), %sp
526
527 #ifdef  save_allregs
528         ld      [%o0 + globals + 32 + 0],%f0            ! Restore floating-point registers 
529         ld      [%o0 + globals + 32 + 4],%f1
530         ld      [%o0 + globals + 32 + 8],%f2
531         ld      [%o0 + globals + 32 + 12],%f3
532         ld      [%o0 + globals + 32 + 16],%f4
533         ld      [%o0 + globals + 32 + 20],%f5
534         ld      [%o0 + globals + 32 + 24],%f6
535         ld      [%o0 + globals + 32 + 28],%f7
536         ld      [%o0 + globals + 64 + 0],%f8
537         ld      [%o0 + globals + 64 + 4],%f9
538         ld      [%o0 + globals + 64 + 8],%f10
539         ld      [%o0 + globals + 64 + 12],%f11
540         ld      [%o0 + globals + 64 + 16],%f12
541         ld      [%o0 + globals + 64 + 20],%f13
542         ld      [%o0 + globals + 64 + 24],%f14
543         ld      [%o0 + globals + 64 + 28],%f15
544         ld      [%o0 + globals + 64 + 32],%f16
545         ld      [%o0 + globals + 64 + 36],%f17
546         ld      [%o0 + globals + 64 + 40],%f18
547         ld      [%o0 + globals + 64 + 44],%f19
548         ld      [%o0 + globals + 64 + 48],%f20
549         ld      [%o0 + globals + 64 + 52],%f21
550         ld      [%o0 + globals + 64 + 56],%f22
551         ld      [%o0 + globals + 64 + 60],%f23
552         ld      [%o0 + globals + 64 + 64],%f24
553         ld      [%o0 + globals + 64 + 68],%f25
554         ld      [%o0 + globals + 64 + 72],%f26
555         ld      [%o0 + globals + 64 + 76],%f27
556         ld      [%o0 + globals + 64 + 80],%f28
557         ld      [%o0 + globals + 64 + 84],%f29
558         ld      [%o0 + globals + 64 + 88],%f30
559         ld      [%o0 + globals + 64 + 92],%f31
560 #ifdef  notdef
561         ld      [%o0 + globals + 64 + 96],%g1
562         mov     %g1, %fsr
563         ld      [%o0 + globals + 64 + 100],%g1
564         mov     %g1, %fq
565 #endif
566
567         ld      [%o0 + globals + 168 + 0],%c0           ! Restore floating-point registers 
568         ld      [%o0 + globals + 168 + 4],%c1
569         ld      [%o0 + globals + 168 + 8],%c2
570         ld      [%o0 + globals + 168 + 12],%c3
571         ld      [%o0 + globals + 168 + 16],%c4
572         ld      [%o0 + globals + 168 + 20],%c5
573         ld      [%o0 + globals + 168 + 24],%c6
574         ld      [%o0 + globals + 168 + 28],%c7
575         ld      [%o0 + globals + 200 + 0],%c8
576         ld      [%o0 + globals + 200 + 4],%c9
577         ld      [%o0 + globals + 200 + 8],%c10
578         ld      [%o0 + globals + 200 + 12],%c11
579         ld      [%o0 + globals + 200 + 16],%c12
580         ld      [%o0 + globals + 200 + 20],%c13
581         ld      [%o0 + globals + 200 + 24],%c14
582         ld      [%o0 + globals + 200 + 28],%c15
583         ld      [%o0 + globals + 200 + 32],%c16
584         ld      [%o0 + globals + 200 + 36],%c17
585         ld      [%o0 + globals + 200 + 40],%c18
586         ld      [%o0 + globals + 200 + 44],%c19
587         ld      [%o0 + globals + 200 + 48],%c20
588         ld      [%o0 + globals + 200 + 52],%c21
589         ld      [%o0 + globals + 200 + 56],%c22
590         ld      [%o0 + globals + 200 + 60],%c23
591         ld      [%o0 + globals + 200 + 64],%c24
592         ld      [%o0 + globals + 200 + 68],%c25
593         ld      [%o0 + globals + 200 + 72],%c26
594         ld      [%o0 + globals + 200 + 76],%c27
595         ld      [%o0 + globals + 200 + 80],%c28
596         ld      [%o0 + globals + 200 + 84],%c29
597         ld      [%o0 + globals + 200 + 88],%c30
598         ld      [%o0 + globals + 200 + 92],%c31
599 #ifdef  notdef
600         ld      [%o0 + globals + 200 + 96],%g1
601         mov     %g1, %csr
602         ld      [%o0 + globals + 200 + 100],%g1
603         mov     %g1, %cq
604 #endif
605 #endif
606         ld      [%o0 + globals + 28], %g1               ! Restore global regs back
607         mov     %g1, %y
608         ld      [%o0 + globals + 0], %g1
609         ld      [%o0 + globals + 4], %g2
610         ld      [%o0 + globals + 8], %g3
611         ld      [%o0 + globals + 12],%g4
612         ld      [%o0 + globals + 16],%g5
613         ld      [%o0 + globals + 20],%g6
614         ld      [%o0 + globals + 24],%g7
615
616         /* The following 3 lines are equivalent to: _PRE_Block = 0 */
617 #ifdef  AFS_SUN5_ENV
618         set     PRE_Block, %l0
619 #else
620         set     _PRE_Block, %l0
621 #endif
622         mov     0,%l1
623         stb     %l1, [%l0]
624
625         restore                                 
626         restore
627
628         retl
629         nop
630
631 #endif /* sparc */
632 #ifdef ibm032
633 |
634 |       Information Technology Center
635 |       Carnegie-Mellon University
636 |
637 |
638         .data
639         .globl  .oVncs
640         .set            .oVncs,0
641
642         .globl  _savecontext
643 _savecontext:
644         .long           _.savecontext
645
646         .globl  _returnto
647 _returnto:
648         .long           _.returnto
649
650 |
651 |       Process assembly language assist for Sailboats.
652 |
653
654         .text
655         .align 2
656
657 |
658 | struct savearea {
659 |       char    *topstack;
660 | }
661 |
662
663 | Offsets of fields
664 .set topstack,0
665
666 | Stuff to allow saving/restoring registers
667 .set regspace,64
668 .set freg,0
669
670 |
671 | savecontext(f, area1, newsp)
672 |    int (*f)(); struct savearea *area1; char *newsp;
673 |
674
675         .globl  _.savecontext
676 _.savecontext:
677         ai      sp,sp,-regspace         | Save frame pointer & ...
678                                         | ... allocate space for 16 registers
679 | Save registers
680         stm     r0,0(sp)                        | Change this if save fewer regs.
681 | Set preemption semaphore
682         get     r6,$1
683         get     r7,$_PRE_Block
684         putc    r6,0(r7)                        | PRE_Block = 1
685 | r3 = base of savearea
686         put     sp,topstack(r3)         | area1->topstack = sp
687 | New sp is in r4.
688         cis     r4,0
689         be      L1                      | If newsp == 0, no stack switch
690         cas     sp,r4,r0                        | Switch to new stack
691 L1:
692         get     r6,0(r2)                        | r2 = _f
693         balrx   r15,r6                  | f()
694         cas     r0,r2,r0
695
696 |
697 | returnto(area2)
698 |     struct savearea *area2;
699 |
700
701         .globl _.returnto
702 _.returnto:
703         get     sp,topstack(r2)
704 | Now in the context of the savecontext stack to be restored.
705 | Start with the registers...
706 | Clear preemption semaphore
707         get     r6,$0
708         get     r7,$_PRE_Block
709         putc    r6,0(r7)                        | PRE_Block = 0
710         lm      r0,0(sp)                | Change if saving fewer regs.
711         brx     r15             | Return to previous process
712         ai      sp,sp,regspace
713  .data
714  .ltorg
715 #endif
716
717 #ifdef AFS_AIX22_ENV
718 /*
719 #
720 #       Information Technology Center
721 #       Carnegie-Mellon University
722 #
723 */
724 /*
725 #
726 #       Process assembly language assist for Sailboats.
727 #
728 */
729
730         .text
731         .globl  .savecontext
732         .align 1
733
734 /*
735 #
736 # struct savearea {
737 #       char    *topstack;
738 # }
739 #
740 */
741
742
743 /*# Offsets of fields*/
744 .set topstack,0
745
746 /*# Stuff to allow saving/restoring registers*/
747 .set regspace,64
748 .set freg,0
749
750 /*
751 #
752 # savecontext(f, area1, newsp)
753 #    int (*f)(); struct savearea *area1; char *newsp;
754 #
755 */
756
757 .savecontext:
758         ai      1,1,-regspace           # Save frame pointer & ...
759
760 /*# Save registers*/
761         stm     0,0(1)                  # Change this if save fewer regs.
762         lr      14,0
763 /*# Set preemption semaphore*/
764         lis     6,1
765         l       7,4(14)
766         stc     6,0(7)
767 /*# r3 = base of savearea*/
768         st      1,topstack(3)           # area1->topstack = sp
769 /*# New sp is in r4.*/
770         ci      4,0
771         beq     L1                      # If newsp == 0, no stack switch
772         cas     1,4,0                   # Switch to new stack
773 L1:
774         l       6,0(2)                  # r2 = _f
775         balrx   15,6                    # f()
776         cas     0,2,0
777         .data   3
778         .globl  _savecontext
779 _savecontext:
780         .long   .savecontext
781         .long   _PRE_Block
782 /*
783 #
784 # returnto(area2)
785 #     struct savearea *area2;
786 #
787 */
788
789         .text
790         .globl  .returnto
791         .align 1
792 .returnto:
793         l       1,topstack(2)
794 /*
795 # Now in the context of the savecontext stack to be restored.
796 # Start with the registers...
797 # Clear preemption semaphore
798 */
799         lr      14,0
800         lis     6,0
801         l       7,4(14)
802         stc     6,0(7)
803         lm      0,0(1)          # Change if saving fewer regs.
804         brx     15              # Return to previous process
805         ai      1,1,regspace
806         .data   3
807         .globl  _returnto
808 _returnto:
809         .long   .returnto
810         .long   _PRE_Block
811 #endif /* AFS_AIX_ENV */
812
813 #ifdef vax
814 /*
815 #
816 #       Information Technology Center
817 #       Carnegie-Mellon University
818 #
819 #
820 */
821         .data
822
823 /*
824 #
825 #       Algorithm: "Monkey see, monkey do"
826 #
827 */
828
829         .text
830
831 /*
832 #
833 # struct savearea {
834 #       char    *topstack;
835 # }
836 #
837 */
838
839         .set    topstack,0
840
841 /* Stuff to allow saving/restoring registers */
842
843 /*
844 # savecontext(f, area1, newsp)
845 #     int (*f)(); struct savearea *area1; char *newsp;
846 */
847
848 /* Stack offsets of arguments */
849         .set    f,4
850         .set    area1,8
851         .set    newsp,12
852
853 .globl  _PRE_Block
854 .globl  _savecontext
855
856 _savecontext:
857         .word 0x0ffc    # Save regs R2-R11
858         movb    $1,_PRE_Block           # Critical section for preemption code
859         pushl   ap                      # save old ap
860         pushl   fp                      # save old fp    
861         movl    area1(ap),r0            # r0 = base of savearea
862         movl    sp,topstack(r0)         # area->topstack = sp
863         movl    newsp(ap),r0            # Get new sp
864         beql    L1                      # if new sp is 0, dont change stacks
865         movl    r0,sp                   # else switch to new stack
866 L1:
867         movl    f(ap),r1                # r1 = f
868         calls   $0,0(r1)                # f()
869
870 /* It is impossible to be here, so abort() */
871
872         calls   $0,_abort
873
874 /*
875 # returnto(area2)
876 #     struct savearea *area2;
877 */
878
879 /* Stack offset of argument */
880         .set    area2,4
881
882         .globl _returnto
883 _returnto:
884         .word   0x0                     # Who cares about these regs?
885         movl    area2(ap),r0            # r0 = address of area2
886         movl    topstack(r0),sp         # Restore sp
887         movl    (sp)+,fp                # Restore fp
888         movl    (sp)+,ap                # ,,,,
889         clrb    _PRE_Block              # End of preemption critical section
890         ret
891
892         pushl   $1234                   # The author will gloat
893         calls   $0,_abort
894 #endif
895
896 #ifdef mips
897 #ifdef  sgi
898         .option pic2
899
900 #include <regdef.h> /* Allow use of symbolic names for registers. */
901 /* 9 sregs, ra, 6 fp regs, gp, pad to 8 byte boundary */
902 #define regspace 9 * 4 + 4 + 6 * 8 + 4 + 4
903 #define floats 0
904 #define registers floats + 6 * 8
905 #define returnaddr regspace - 4
906 #define topstack 0
907 #define GPOFF   regspace - 8
908         .globl savecontext /* MIPS' C compiler doesnt prepend underscores. */
909         .ent savecontext /* Insert debugger information. */
910 savecontext:
911         .set    noreorder
912         .cpload t9                      # set up gp for KPIC
913         .set    reorder
914         subu sp, regspace
915         .cprestore GPOFF                # trigger t9/jalr
916         .set    noreorder
917         li      t0, 1
918         .extern PRE_Block
919         sb      t0, PRE_Block
920         .set    reorder
921         .frame  sp, regspace, ra
922 /* Save registers. */
923         sw      s0, registers + 0(sp)
924         sw      s1, registers + 4(sp)
925         sw      s2, registers + 8(sp)
926         sw      s3, registers + 12(sp)
927         sw      s4, registers + 16(sp)
928         sw      s5, registers + 20(sp)
929         sw      s6, registers + 24(sp)
930         sw      s7, registers + 28(sp)
931         sw      s8, registers + 32(sp)
932 /* Save return address */
933         sw      ra, returnaddr(sp)
934         .mask   0xc0ff0000, -4
935 /* Need to save floating point registers? */
936         s.d     $f20, floats + 0(sp)
937         s.d     $f22, floats + 8(sp)
938         s.d     $f24, floats + 16(sp)
939         s.d     $f26, floats + 24(sp)
940         s.d     $f28, floats + 32(sp)
941         s.d     $f30, floats + 40(sp)
942         .fmask  0x55400000, regspace
943         sw      sp, topstack(a1)
944         beq     a2, $0, samestack
945         move    sp, a2
946 samestack:
947         move    t9, a0
948         j       t9
949         .end    savecontext
950
951         .globl  returnto
952         .ent    returnto
953 returnto:
954         .set    noreorder
955         .cpload t9                      # set up gp for KPIC
956         .set    reorder
957
958         lw      sp, topstack(a0)
959         lw      s0, registers + 0(sp)
960         lw      s1, registers + 4(sp)
961         lw      s2, registers + 8(sp)
962         lw      s3, registers + 12(sp)
963         lw      s4, registers + 16(sp)
964         lw      s5, registers + 20(sp)
965         lw      s6, registers + 24(sp)
966         lw      s7, registers + 28(sp)
967         lw      s8, registers + 32(sp)
968 /* Save return address */
969         lw      ra, returnaddr(sp)
970 /* Need to save floating point registers? */
971         l.d     $f20, floats + 0(sp)
972         l.d     $f22, floats + 8(sp)
973         l.d     $f24, floats + 16(sp)
974         l.d     $f26, floats + 24(sp)
975         l.d     $f28, floats + 32(sp)
976         l.d     $f30, floats + 40(sp)
977         .set    noreorder
978         addu    sp, regspace
979         la      t0, PRE_Block
980         j       ra
981         sb      zero, 0(t0)
982         .set    reorder
983         .end    returnto
984
985 #else
986 /* Code for MIPS R2000/R3000 architecture
987  * Written by Zalman Stern April 30th, 1989.
988  */
989 #include <regdef.h> /* Allow use of symbolic names for registers. */
990 #define regspace 9 * 4 + 4 + 6 * 8
991 #define floats 0
992 #define registers floats + 6 * 8
993 #define returnaddr regspace - 4
994 #define topstack 0
995         .globl savecontext /* MIPS' C compiler doesnt prepend underscores. */
996         .ent savecontext /* Insert debugger information. */
997 savecontext:
998         li      t0, 1
999         .extern PRE_Block
1000         sb      t0, PRE_Block
1001         subu    sp, regspace
1002         .frame  sp, regspace, ra
1003 /* Save registers. */
1004         sw      s0, registers + 0(sp)
1005         sw      s1, registers + 4(sp)
1006         sw      s2, registers + 8(sp)
1007         sw      s3, registers + 12(sp)
1008         sw      s4, registers + 16(sp)
1009         sw      s5, registers + 20(sp)
1010         sw      s6, registers + 24(sp)
1011         sw      s7, registers + 28(sp)
1012         sw      s8, registers + 32(sp)
1013 /* Save return address */
1014         sw      ra, returnaddr(sp)
1015         .mask   0xc0ff0000, -4
1016 /* Need to save floating point registers? */
1017         s.d     $f20, floats + 0(sp)
1018         s.d     $f22, floats + 8(sp)
1019         s.d     $f24, floats + 16(sp)
1020         s.d     $f26, floats + 24(sp)
1021         s.d     $f28, floats + 32(sp)
1022         s.d     $f30, floats + 40(sp)
1023         .fmask  0x55400000, regspace
1024         sw      sp, topstack(a1)
1025         beq     a2, $0, samestack
1026         addu    sp, $0, a2
1027 samestack:
1028         jal     a0
1029         .end    savecontext
1030
1031         .globl  returnto
1032         .ent    returnto
1033 returnto:
1034         lw      sp, topstack(a0)
1035         lw      s0, registers + 0(sp)
1036         lw      s1, registers + 4(sp)
1037         lw      s2, registers + 8(sp)
1038         lw      s3, registers + 12(sp)
1039         lw      s4, registers + 16(sp)
1040         lw      s5, registers + 20(sp)
1041         lw      s6, registers + 24(sp)
1042         lw      s7, registers + 28(sp)
1043         lw      s8, registers + 32(sp)
1044 /* Save return address */
1045         lw      ra, returnaddr(sp)
1046 /* Need to save floating point registers? */
1047         l.d     $f20, floats + 0(sp)
1048         l.d     $f22, floats + 8(sp)
1049         l.d     $f24, floats + 16(sp)
1050         l.d     $f26, floats + 24(sp)
1051         l.d     $f28, floats + 32(sp)
1052         l.d     $f30, floats + 40(sp)
1053         addu    sp, regspace
1054         sb      $0, PRE_Block
1055         j       ra
1056         .end    returnto
1057 #endif  /* sgi */
1058 #endif
1059
1060 #ifdef AFS_HPUX_ENV
1061 #include "process.s.hpux"
1062 #endif /* AFS_HPUX_ENV */
1063
1064 #ifdef __alpha
1065 /* Code for DEC Alpha architecture */
1066 #ifdef  AFS_OSF_ENV
1067 #include <machine/asm.h>
1068 #include <machine/regdef.h>
1069 #define fs0     $f2
1070 #define fs1     $f3
1071 #define fs2     $f4
1072 #define fs3     $f5
1073 #define fs4     $f6
1074 #define fs5     $f7
1075 #define fs6     $f8
1076 #define fs7     $f9
1077 #elif defined(AFS_XBSD_ENV)
1078 #include <machine/asm.h>
1079 #else   /* !OSF && !XBSD */
1080 #include <mach/alpha/asm.h>
1081 #endif  /* OSF */
1082
1083 #define FRAMESIZE ((8*8)+8+(7*8))
1084 #define floats 0
1085 #define registers (floats+(8*8))
1086 #define returnaddr (FRAMESIZE-8)
1087 #define topstack 0
1088
1089 #ifdef AFS_OSF_ENV
1090 IMPORT(PRE_Block,4)
1091 #endif
1092 .align  4
1093 #ifdef  AFS_OSF_ENV
1094 NESTED(savecontext,FRAMESIZE,ra)
1095 #else   /* OSF */
1096 NESTED(savecontext,3,FRAMESIZE,ra,0x0400f700,0x000003fc)
1097 #endif  /* OSF */
1098         ldgp    gp,0(pv)
1099         lda     t0, 1(zero)
1100         stl     t0, PRE_Block
1101         lda     sp,-FRAMESIZE(sp)
1102 /* Save callee-saved registers. */
1103         stq     s0, (registers+0) (sp)
1104         stq     s1, (registers+8) (sp)
1105         stq     s2, (registers+16) (sp)
1106         stq     s3, (registers+24) (sp)
1107         stq     s4, (registers+32) (sp)
1108         stq     s5, (registers+40) (sp)
1109         stq     s6, (registers+48) (sp)
1110 /* Save return address */
1111         stq     ra, returnaddr(sp)
1112
1113         .mask   (M_S0|M_S1|M_S2|M_S3|M_S4|M_S5|M_S6|M_RA), -FRAMESIZE
1114
1115 /* Save floating point registers */
1116         stt     fs0, (floats+0) (sp)
1117         stt     fs1, (floats+8) (sp)
1118         stt     fs2, (floats+16) (sp)
1119         stt     fs3, (floats+24) (sp)
1120         stt     fs4, (floats+32) (sp)
1121         stt     fs5, (floats+40) (sp)
1122         stt     fs6, (floats+48) (sp)
1123         stt     fs7, (floats+56) (sp)
1124
1125         .prologue       1
1126         stq     sp, topstack(a1)
1127         or      a0,zero,pv              /* call point in pv */
1128         beq     a2, samestack
1129         or      a2,zero,sp              /* switch stack */
1130 samestack:
1131         jsr     ra,(pv),0               /* off we go */
1132         END(savecontext)
1133
1134 #ifdef  AFS_OSF_ENV
1135 LEAF(returnto)
1136 #else   
1137 LEAF(returnto,1)
1138 #endif  
1139         ldgp    gp,0(pv)
1140
1141         .prologue       1
1142         ldq     sp, topstack(a0)
1143 /* Restore callee-saved regs */
1144         ldq     s0, (registers+0) (sp)
1145         ldq     s1, (registers+8) (sp)
1146         ldq     s2, (registers+16) (sp)
1147         ldq     s3, (registers+24) (sp)
1148         ldq     s4, (registers+32) (sp)
1149         ldq     s5, (registers+40) (sp)
1150         ldq     s6, (registers+48) (sp)
1151 /* Return address */
1152         ldq     ra, returnaddr(sp)
1153 /* Floating point registers */
1154         ldt     fs0, (floats+0) (sp)
1155         ldt     fs1, (floats+8) (sp)
1156         ldt     fs2, (floats+16) (sp)
1157         ldt     fs3, (floats+24) (sp)
1158         ldt     fs4, (floats+32) (sp)
1159         ldt     fs5, (floats+40) (sp)
1160         ldt     fs6, (floats+48) (sp)
1161         ldt     fs7, (floats+56) (sp)
1162         lda     sp, FRAMESIZE(sp)
1163         stl     zero, PRE_Block
1164         RET
1165         END(returnto)
1166 #endif
1167
1168 #if defined(AFS_NCR_ENV) || defined(AFS_X86_ENV) || defined(AFS_DJGPP_ENV) || defined(AFS_OBSD_ENV)
1169 /* Sun 386i... I hope this does the right thing!!!
1170  * 
1171  * Written by Derek Atkins <warlord@MIT.EDU>
1172  * (debugging help by Chris Provenzano <proven@mit.edu>)
1173  * 11/1991
1174  *
1175  * "ojala que es correcto!"
1176  */
1177         .file "process.s"
1178
1179         .data
1180
1181         .text
1182
1183 /*
1184  * struct savearea {
1185  *      char    *topstack;
1186  * }
1187  */
1188
1189         .set    topstack,0
1190
1191 /*
1192  * savecontext(f, area1, newsp)
1193  *      int (*f)(); struct savearea *area1; char *newsp;
1194  */
1195
1196 /* offsets, to make my life easier! */
1197         .set    f,8
1198         .set    area1,12
1199         .set    newsp,16
1200
1201
1202 #if defined(AFS_DJGPP_ENV) || defined(AFS_XBSD_ENV)
1203 .globl  _PRE_Block
1204 .globl  _savecontext
1205 _savecontext:
1206 #else
1207 .globl  PRE_Block
1208 .globl  savecontext
1209 savecontext:
1210 #endif /* AFS_DJGPP_ENV */
1211         pushl   %ebp                    /* New Frame! */
1212         movl    %esp,%ebp
1213         pusha                           /* Push all registers */
1214 #if defined(AFS_DJGPP_ENV) || defined(AFS_XBSD_ENV)
1215         movl    $1,_PRE_Block           /* Pre-emption code */
1216 #else
1217         movl    $1,PRE_Block            /* Pre-emption code */
1218 #endif /* AFS_DJGPP_ENV */
1219         movl    area1(%ebp),%eax        /* eax = base of savearea */
1220         movl    %esp,(%eax)             /* area->topstack = esp */
1221         movl    newsp(%ebp),%eax        /* get new sp into eax */
1222         cmpl    $0,%eax
1223         je      L1                      /* if new sp is 0 then dont change esp */
1224         movl    %eax,%esp               /* go ahead.  make my day! */
1225 L1:
1226         jmp     *f(%ebp)                        /* ebx = &f */
1227
1228 /* Shouldnt be here....*/
1229
1230 #if defined(AFS_DJGPP_ENV) || defined(AFS_XBSD_ENV)
1231         call    _abort
1232 #else
1233         call    abort
1234 #endif /* AFS_DJGPP_ENV */
1235
1236 /*
1237  * returnto(area2)
1238  *      struct savearea *area2;
1239  */
1240
1241 /* stack offset */
1242         .set    area2,8
1243
1244 #if defined(AFS_DJGPP_ENV) || defined(AFS_XBSD_ENV)
1245 .globl  _returnto
1246 _returnto:
1247 #else
1248 .globl  returnto
1249 returnto:
1250 #endif /* AFS_DJGPP_ENV */
1251         pushl   %ebp
1252         movl    %esp, %ebp              /* New frame, to get correct pointer */
1253         movl    area2(%ebp),%eax        /* eax = area2 */
1254         movl    (%eax),%esp             /* restore esp */
1255         popa 
1256 #if defined(AFS_DJGPP_ENV) || defined(AFS_XBSD_ENV)
1257         movl    $0,_PRE_Block           /* clear it up... */
1258 #else
1259         movl    $0,PRE_Block            /* clear it up... */
1260 #endif /* AFS_DJGPP_ENV */
1261         popl    %ebp
1262         ret
1263
1264 /* I see, said the blind man, as he picked up his hammer and saw! */
1265         pushl   $1234
1266 #if defined(AFS_DJGPP_ENV) || defined(AFS_XBSD_ENV)
1267         call    _abort
1268 #else
1269         call    abort
1270 #endif /* AFS_DJGPP_ENV */
1271
1272
1273 #endif /* AFS_NCR_ENV */
1274 #ifdef AFS_PPC_ENV
1275 /* Comments:
1276  *    1. Registers R10..R31 and CR0..CR7 are saved
1277  *    2. "struct savearea" must hold at least 3 pointers (long)
1278  *    3. This code will only work on 32 bit machines (601..604), not 620
1279  *    4. No floating point registers are saved
1280  *    5. The save stack "frame" is bigger than absolutely necessary.  The
1281  *       PowerPC [AIX] ABI needs this extra space.
1282  */
1283
1284
1285 /* Mach-O assemblers */
1286 #if !defined(NeXT) && !defined(__APPLE__)
1287 #define r0    0
1288 #define r1    1
1289 #define r2    2
1290 #define r3    3
1291 #define r4    4
1292 #define r5    5
1293 #define r6    6
1294 #define r7    7
1295 #define r8    8
1296 #define r9    9
1297 #define r10   10
1298 #define r11   11
1299 #define r12   12
1300 #define r13   13
1301 #define r14   14
1302 #define r15   15
1303 #define r16   16
1304 #define r17   17
1305 #define r18   18
1306 #define r19   19
1307 #define r20   20
1308 #define r21   21
1309 #define r22   22
1310 #define r23   23
1311 #define r24   24
1312 #define r25   25
1313 #define r26   26
1314 #define r27   27
1315 #define r28   28
1316 #define r29   29
1317 #define r30   30
1318 #define r31   31
1319 #endif /* !NeXT && !__APPLE__ */
1320
1321
1322 /*
1323  * savecontext(int (*f)(), struct savearea *save, char *newsp)
1324  */
1325
1326 #define FRAME_SIZE    (32*4)+(8*4)
1327 #define FRAME_OFFSET  (8*4)
1328 #define TOP_OF_STACK  (0*4)
1329 #define RETURN                (1*4)
1330 #define CCR           (2*4)
1331
1332 #if defined(NeXT) || defined(__APPLE__)
1333       .globl  _savecontext
1334 _savecontext:
1335       lis     r9,ha16(_PRE_Block)     /* Disable interrupt fiddling */
1336       li      r8,1
1337       stb     r8,lo16(_PRE_Block)(r9)
1338 #else
1339       .globl  savecontext
1340 savecontext:
1341       lis     r9,PRE_Block@ha         /* Disable interrupt fiddling */
1342       li      r8,1
1343       stb     r8,PRE_Block@l(r9)
1344 #endif /* NeXT || __APPLE__ */
1345       subi    r1,r1,FRAME_SIZE
1346       mfcr    r9
1347       stw     r9,CCR(r4)
1348       stw     r10,10*4+FRAME_OFFSET(r1)       /* Save registers */
1349       stw     r11,11*4+FRAME_OFFSET(r1)
1350       stw     r12,12*4+FRAME_OFFSET(r1)
1351       stw     r13,13*4+FRAME_OFFSET(r1)
1352       stw     r14,14*4+FRAME_OFFSET(r1)
1353       stw     r15,15*4+FRAME_OFFSET(r1)
1354       stw     r16,16*4+FRAME_OFFSET(r1)
1355       stw     r17,17*4+FRAME_OFFSET(r1)
1356       stw     r18,18*4+FRAME_OFFSET(r1)
1357       stw     r19,19*4+FRAME_OFFSET(r1)
1358       stw     r20,20*4+FRAME_OFFSET(r1)
1359       stw     r21,21*4+FRAME_OFFSET(r1)
1360       stw     r22,22*4+FRAME_OFFSET(r1)
1361       stw     r23,23*4+FRAME_OFFSET(r1)
1362       stw     r24,24*4+FRAME_OFFSET(r1)
1363       stw     r25,25*4+FRAME_OFFSET(r1)
1364       stw     r26,26*4+FRAME_OFFSET(r1)
1365       stw     r27,27*4+FRAME_OFFSET(r1)
1366       stw     r28,28*4+FRAME_OFFSET(r1)
1367       stw     r29,29*4+FRAME_OFFSET(r1)
1368       stw     r30,30*4+FRAME_OFFSET(r1)
1369       stw     r31,31*4+FRAME_OFFSET(r1)
1370       stw     r1,TOP_OF_STACK(r4)
1371       cmpi    0,r5,0                          /* New stack specified? */
1372       mflr    r0
1373       stw     r0,RETURN(r4)
1374       mtlr    r3
1375       beq     L1                             /* No - don't muck with pointer */
1376
1377       mr      r1,r5
1378 L1:        blr                                     /* Return */
1379
1380 /*
1381  * returnto(struct savearea *area)
1382  */
1383 #if defined(NeXT) || defined(__APPLE__)
1384       .globl  _returnto
1385 _returnto:
1386 #else
1387       .globl  returnto
1388 returnto:
1389 #endif /* NeXT || __APPLE__ */
1390       lwz     r1,TOP_OF_STACK(r3)             /* Update stack pointer */
1391       lwz     r0,RETURN(r3)                   /* Get return address */
1392       mtlr    r0
1393       lwz     r4,CCR(r3)
1394       mtcrf   0xFF,r4
1395       lwz     r10,10*4+FRAME_OFFSET(r1)       /* Restore registers */
1396       lwz     r11,11*4+FRAME_OFFSET(r1)
1397       lwz     r12,12*4+FRAME_OFFSET(r1)
1398       lwz     r13,13*4+FRAME_OFFSET(r1)
1399       lwz     r14,14*4+FRAME_OFFSET(r1)
1400       lwz     r15,15*4+FRAME_OFFSET(r1)
1401       lwz     r16,16*4+FRAME_OFFSET(r1)
1402       lwz     r17,17*4+FRAME_OFFSET(r1)
1403       lwz     r18,18*4+FRAME_OFFSET(r1)
1404       lwz     r19,19*4+FRAME_OFFSET(r1)
1405       lwz     r20,20*4+FRAME_OFFSET(r1)
1406       lwz     r21,21*4+FRAME_OFFSET(r1)
1407       lwz     r22,22*4+FRAME_OFFSET(r1)
1408       lwz     r23,23*4+FRAME_OFFSET(r1)
1409       lwz     r24,24*4+FRAME_OFFSET(r1)
1410       lwz     r25,25*4+FRAME_OFFSET(r1)
1411       lwz     r26,26*4+FRAME_OFFSET(r1)
1412       lwz     r27,27*4+FRAME_OFFSET(r1)
1413       lwz     r28,28*4+FRAME_OFFSET(r1)
1414       lwz     r29,29*4+FRAME_OFFSET(r1)
1415       lwz     r30,30*4+FRAME_OFFSET(r1)
1416       lwz     r31,31*4+FRAME_OFFSET(r1)
1417 #if defined(NeXT) || defined(__APPLE__)
1418       lis     r9,ha16(_PRE_Block)         /* Re-enable interrupt fiddling */
1419       li      r8,0
1420       stb     r8,lo16(_PRE_Block)(r9)
1421 #else
1422       lis     r9,PRE_Block@ha         /* Re-enable interrupt fiddling */
1423       li      r8,0
1424       stb     r8,PRE_Block@l(r9)
1425 #endif /* NeXT || __APPLE__ */
1426       addi    r1,r1,FRAME_SIZE
1427       blr
1428 #endif
1429