* asm_handle_exception: Much better, simpler and smaller implementation
[cacao.git] / src / vm / jit / i386 / asmpart.S
1 /* src/vm/jit/i386/asmpart.S - Java-C interface functions for i386
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Andreas Krall
28             Reinhard Grafl
29             Christian Thalinger
30
31    Changes: Joseph Wenninger
32
33    $Id: asmpart.S 3894 2005-12-06 22:30:30Z twisti $
34
35 */
36
37
38 #include "config.h"
39 #include "vm/jit/i386/offsets.h"
40
41 #include "vm/jit/methodheader.h"
42
43
44 /* define it like the risc way */
45
46 #define v0       %eax
47
48 #define sp       %esp
49 #define bp       %ebp
50
51 #define itmp1    %eax
52 #define itmp2    %ecx
53 #define itmp3    %edx
54
55 #define itmp1b   %al
56 #define itmp2b   %cl
57 #define itmp3b   %dl
58
59 #define xptr     itmp1
60 #define xpc      itmp2
61
62
63         .text
64
65
66 /********************* exported functions and variables ***********************/
67
68         .globl asm_calljavafunction
69         .globl asm_calljavafunction_int
70
71         .globl asm_calljavafunction2
72         .globl asm_calljavafunction2int
73         .globl asm_calljavafunction2long
74         .globl asm_calljavafunction2float
75         .globl asm_calljavafunction2double
76
77         .globl asm_call_jit_compiler
78         .globl asm_handle_nat_exception
79         .globl asm_handle_exception
80
81         .globl asm_wrapper_patcher
82
83         .globl asm_builtin_f2i
84         .globl asm_builtin_f2l
85         .globl asm_builtin_d2i
86         .globl asm_builtin_d2l
87
88         .globl asm_perform_threadswitch
89         .globl asm_initialize_thread_stack
90         .globl asm_switchstackandcall
91         .globl asm_criticalsections
92         .globl asm_getclassvalues_atomic
93
94
95 /********************* function asm_calljavafunction ***************************
96 *                                                                              *
97 *   This function calls a Java-method (which possibly needs compilation)       *
98 *   with up to 4 address parameters.                                           *
99 *                                                                              *
100 *   This functions calls the JIT-compiler which eventually translates the      *
101 *   method into machine code.                                                  *
102 *                                                                              *
103 *   C-prototype:                                                               *
104 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
105 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
106 *                                                                              *
107 *******************************************************************************/
108
109 call_name:
110         .align  8
111
112         .long   0                         /* catch type all                       */
113         .long   calljava_xhandler         /* handler pc                           */
114         .long   calljava_xhandler         /* end pc                               */
115         .long   asm_calljavafunction      /* start pc                             */
116         .long   1                         /* extable size                         */
117         .long   0                         /* line number table start              */
118         .long   0                         /* line number table size               */
119         .long   0                         /* fltsave                              */
120         .long   0                         /* intsave                              */
121         .long   0                         /* isleaf                               */
122         .long   0                         /* IsSync                               */
123         .long   32                        /* frame size                           */
124         .long   0                         /* method pointer (pointer to name)     */
125
126 asm_calljavafunction:
127 asm_calljavafunction_int:
128         push    %ebp                      /* allocate stack space                 */
129         mov     %esp, %ebp
130
131         push    %ebx                      /* save registers                       */
132         push    %esi
133         push    %edi
134
135
136         sub             $16,%esp                    /* 4 adress parameters * 4 Bytes      */
137         mov     24(%ebp),%eax               /* copy adress parameters to new block*/
138         mov     %eax,12(%esp)
139                 
140         mov     20(%ebp),%eax
141         mov     %eax,8(%esp)
142
143         mov     16(%ebp),%eax
144         mov     %eax,4(%esp)
145
146         mov     12(%ebp),%eax
147         mov     %eax,(%esp)
148                 
149         mov     8(%ebp),%eax                /* move function pointer to %eax      */
150
151         lea     asm_call_jit_compiler,%edx 
152         call    *%edx                       /* call JIT compiler                  */
153
154         add     $16,%esp
155         pop     %edi                        /* restore registers                  */
156         pop     %esi
157         pop     %ebx
158         leave
159         ret
160
161 calljava_xhandler:
162         push    %eax                        /* pass exception pointer             */
163         call    builtin_throw_exception
164         add     $4,%esp
165
166         add     $16,%esp
167         pop     %edi                        /* restore registers                  */
168         pop     %esi
169         pop     %ebx
170         leave
171         xor     v0,v0                       /* return NULL                        */
172         ret
173
174
175 /********************* function asm_calljavafunction ***************************
176 *                                                                              *
177 *   This function calls a Java-method (which possibly needs compilation)       *
178 *   with up to 4 address parameters.                                           *
179 *                                                                              *
180 *   This functions calls the JIT-compiler which eventually translates the      *
181 *   method into machine code.                                                  *
182 *                                                                              *
183 *   C-prototype:                                                               *
184 *    javaobject_header *asm_calljavafunction2(methodinfo *m,                   *
185 *         u4 count, u4 size, void *callblock);                                 *
186 *                                                                              *
187 *******************************************************************************/
188
189 call_name2:
190         .align  8
191
192         .long   0                         /* catch type all                       */
193         .long   calljava_xhandler2        /* handler pc                           */
194         .long   calljava_xhandler2        /* end pc                               */
195         .long   asm_calljavafunction2     /* start pc                             */
196         .long   1                         /* extable size                         */
197         .long   0                         /* line number table start              */
198         .long   0                         /* line number table size               */
199         .long   0                         /* fltsave                              */
200         .long   0                         /* intsave                              */
201         .long   0                         /* isleaf                               */
202         .long   0                         /* IsSync                               */
203         .long   32                        /* frame size                           */
204         .long   0                         /* method pointer (pointer to name)     */
205
206 asm_calljavafunction2:
207 asm_calljavafunction2int:
208 asm_calljavafunction2long:
209 asm_calljavafunction2float:
210 asm_calljavafunction2double:
211         push    %ebp
212         mov     %esp,%ebp                 /* save stackptr                        */
213
214         push    %ebx                      /* save registers                       */
215         push    %esi
216         push    %edi
217
218         mov     20(%ebp),%eax             /* pointer to arg block (4(push)+4(return)+4+4+4)*/
219         mov     12(%ebp),%ecx             /* arg count            (4(push)+4(return)+4     */
220
221         xor     %esi,%esi                 /* clear stackframe size (MUST be       */
222                                           /* before args check, may be zero!!!)   */
223         test    %ecx,%ecx                 /* maybe we have no args                */
224         jle     calljava_copydone
225
226         mov     %ecx,%edx                 /* calculate stack size                 */
227         mov     %eax,%edi                 /* save pointer to arg block            */
228
229 calljava_calcstacksize:
230         mov     offjniitemtype(%eax),%ebx
231         test    $1,%ebx                   /* two word type?                       */
232         jz      calljava_onewordtype
233         add     $4,%esi                   /* add 1 slot to stackframe size        */
234
235 calljava_onewordtype:
236         add     $4,%esi                   /* add 1 slot to stackframe size        */
237         sub     $1,%edx
238         test    %edx,%edx                 /* any args left?                       */
239         jz      calljava_setstack
240         add     $sizejniblock,%eax        /* goto next argument block             */
241         jmp     calljava_calcstacksize
242                 
243 calljava_setstack:                              
244         mov     %edi,%eax                 /* restore pointer to arg block         */
245         sub     %esi,%esp                 /* create stackframe for arguments      */
246         mov     %esp,%edi                 /* move stackpointer into temp variable */
247
248 calljava_copyloop:
249         mov     offjniitem(%eax),%edx     /* copy 4 Byte of Argument              */
250         mov     %edx,(%edi)
251         add     $4,%edi                   /* increase sp to next argument         */
252         mov     offjniitemtype(%eax),%ebx /* type -> ebx                          */
253         test    $1,%ebx                   /* Two Word Type?                       */
254         jz      calljava_copynext
255
256         mov     offjniitem+4(%eax),%edx   /* copy upper 4 Byte of 2 Word Type     */
257         mov     %edx,(%edi)                     
258         add     $4,%edi                   /* increase sp to next argument         */
259
260 calljava_copynext:              
261         sub     $1,%ecx                   /* are there any args left?             */
262         test    %ecx,%ecx
263         jle     calljava_copydone
264
265         add     $sizejniblock,%eax        /* goto next argument block             */
266         jmp     calljava_copyloop
267
268 calljava_copydone:
269         mov     8(%ebp),%eax              /* move function pointer to %eax        */
270
271         lea     asm_call_jit_compiler,%edx 
272         call    *%edx                     /* call JIT compiler                    */
273         
274         add     %esi,%esp                 /* remove arg stack frame               */
275         pop     %edi                      /* restore registers                    */
276         pop     %esi
277         pop     %ebx
278         leave
279         ret
280
281 calljava_xhandler2:
282         push    xptr                      /* pass exception pointer               */
283         call    builtin_throw_exception
284         add     $4,%esp
285     
286         add     %esi,%esp                 /* remove arg stack frame               */
287         pop     %edi                      /* restore registers                    */
288         pop     %esi
289         pop     %ebx
290         leave
291         xor     v0,v0                     /* return NULL                          */
292         ret
293
294
295 /****************** function asm_call_jit_compiler *****************************
296 *                                                                              *
297 *   invokes the compiler for untranslated JavaVM methods.                      *
298 *                                                                              *
299 *   Register R0 contains a pointer to the method info structure (prepared      *
300 *   by createcompilerstub). Using the return address in R26 and the            *
301 *   offset in the LDA instruction or using the value in methodptr R28 the      *
302 *   patching address for storing the method address can be computed:           *
303 *                                                                              *
304 *   method address was either loaded using                                     *
305 *                                                                              *
306 *   i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special       *
307 *   i386_call_reg(REG_ITMP2)                                                   *
308 *                                                                              *
309 *   or                                                                         *
310 *                                                                              *
311 *   i386_mov_membase_reg(REG_SP, 0, REG_ITMP1)    ; invokevirtual/interface    *
312 *   i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2)                *
313 *   i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \                *
314 *       sizeof(methodptr) * m->vftblindex, REG_ITMP1)                          *
315 *   i386_call_reg(REG_ITMP1)                                                   *
316 *                                                                              *
317 *   in the static case the method pointer can be computed using the            *
318 *   return address and the lda function following the jmp instruction          *
319 *                                                                              *
320 *******************************************************************************/
321
322 asm_call_jit_compiler:
323         sub     $((4+2)*4+sizestackframeinfo),sp /* create stack frame            */
324         mov     itmp1,(4+0)*4(sp)           /* save method pointer                */
325                         
326         mov     (4+2)*4+sizestackframeinfo(sp),itmp3 /* get return address        */
327         mov     -1(itmp3),itmp1b            /* get function code                  */
328         cmp     $0xd1,itmp1b                /* called with `call *REG_ITMP2'?     */
329         jne             L_not_static_special
330
331         sub     $6,itmp3                    /* calculate address of immediate     */
332         jmp             L_call_jit_compile
333                 
334 L_not_static_special:
335         cmp     $0xd0,itmp1b                /* called with `call *REG_ITMP1'      */
336         jne             L_not_virtual_interface
337         
338         sub     $6,itmp3                    /* calculate address of offset        */
339         mov     (itmp3),itmp3               /* get offset                         */
340         add     itmp2,itmp3                 /* add base address to get method adr */
341         jmp             L_call_jit_compile
342
343 L_not_virtual_interface:
344         xor     itmp3,itmp3                 /* a call from asm_calljavafunction   */
345                 
346 L_call_jit_compile:
347         mov     itmp3,(4+1)*4(sp)           /* save address for method pointer    */
348
349         mov     sp,itmp1                    /* create stackframe info             */
350         add     $((4+2)*4),itmp1
351         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
352         movl    $0,1*4(sp)                  /* if pv is NULL, use findmethod      */
353         mov     sp,itmp2
354         add     $((1+4+2)*4+sizestackframeinfo),itmp2 /* pass java sp             */
355         mov     itmp2,2*4(sp)
356         mov     ((0+4+2)*4+sizestackframeinfo)(sp),itmp3 /* pass java ra          */
357         mov     itmp3,3*4(sp)
358         call    stacktrace_create_inline_stackframeinfo
359
360         mov     (4+0)*4(sp),itmp1           /* pass method pointer                */
361         mov     itmp1,0*4(sp)
362         call    jit_compile
363         mov     v0,(4+0)*4(sp)              /* save return value                  */
364
365         mov     sp,itmp1                    /* remove stackframe info             */
366         add     $((4+2)*4),itmp1
367         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
368         call    stacktrace_remove_stackframeinfo
369
370         mov     (4+0)*4(sp),v0              /* restore return value               */
371         mov     (4+1)*4(sp),itmp3           /* restore address for method pointer */
372
373         add     $((4+2)*4+sizestackframeinfo),sp /* remove stack frame            */
374
375         test    v0,v0                       /* check for exception                */
376         je      L_asm_call_jit_compiler_exception
377
378         test    itmp3,itmp3                 /* was this a JIT call?               */
379         je              L_call_method
380         
381         mov     v0,(itmp3)                  /* save the new method pointer        */
382
383 L_call_method:
384         jmp             *v0                         /* ...and now call the new method     */
385
386 L_asm_call_jit_compiler_exception:
387 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
388         call    builtin_asm_get_exceptionptrptr
389         mov     v0,itmp2                    /* v0 == itmp1                        */
390 #else
391         lea     _exceptionptr,itmp2
392 #endif
393         mov     (itmp2),xptr                /* get the exception pointer          */
394         movl    $0,(itmp2)                  /* clear the exception pointer        */
395
396         pop     xpc                         /* get return address                 */
397         sub     $2,xpc                      /* faulting address is ra - 2         */
398         jmp     asm_handle_exception
399
400
401 /* asm_handle_exception ********************************************************
402 *                                                                              *
403 *   This function handles an exception. It does not use the usual calling      *
404 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
405 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
406 *   the local exception table for a handler. If no one is found, it unwinds    *
407 *   stacks and continues searching the callers.                                *
408 *                                                                              *
409 *******************************************************************************/
410
411 asm_handle_nat_exception:
412         add     $4,sp                       /* clear return address of native stub*/
413                 
414 asm_handle_exception:
415 #if 0
416         xor     %edi,%edi                   /* clear indent flag (only first time)*/
417 #endif
418
419 L_asm_handle_exception_stack_loop:
420         sub     $(10*4),sp                   /* create stackframe                  */
421         mov     xptr,4*4(sp)                /* save exception pointer             */
422         mov     xpc,5*4(sp)                 /* save exception pc                  */
423
424 #if 0
425         mov     %ebx,7*4(sp)                /* save registers (non-callee)        */
426         mov     %ebp,8*4(sp)
427 #endif
428
429         mov     xpc,0*4(sp)                 /* pass exception pc                  */
430         call    codegen_findmethod
431         mov     v0,6*4(sp)                  /* save data segment pointer          */
432
433         mov     4*4(sp),itmp3               /* pass exception pointer             */
434         mov     itmp3,0*4(sp)
435         mov     5*4(sp),itmp3               /* pass exception pc                  */
436         mov     itmp3,1*4(sp)
437         mov     v0,2*4(sp)                  /* pass data segment pointer          */
438         mov     sp,itmp3                    /* pass Java stack pointer            */
439         add     $(10*4),itmp3
440         mov     itmp3,3*4(sp)
441         call    exceptions_handle_exception
442
443         test    v0,v0
444         jz      L_asm_handle_exception_not_catched
445
446         mov     v0,xpc                      /* move handlerpc into xpc            */
447         mov     4*4(sp),xptr                /* restore exception pointer          */
448 #if 0
449         mov     7*4(sp),%ebx                /* restore registers (non-callee)     */
450         mov     8*4(sp),%ebp
451 #endif
452         add     $(10*4),sp                   /* free stackframe                    */
453
454         jmp     *xpc                        /* jump to exception handler          */
455
456 L_asm_handle_exception_not_catched:
457         mov     4*4(sp),xptr                /* restore exception pointer          */
458         mov     6*4(sp),itmp3               /* restore data segment pointer       */
459 #if 0
460         mov     7*4(sp),%ebx                /* restore registers (non-callee)     */
461         mov     8*4(sp),%ebp
462 #endif
463         add     $(10*4),sp                   /* free stackframe                    */
464
465         mov     FrameSize(itmp3),itmp2      /* get frame size                     */
466         add     itmp2,sp                    /* unwind stack                       */
467         mov     sp,itmp2                    /* pointer to save area               */
468
469         mov     IntSave(itmp3),%ebx         /* %ecx = saved int register count    */
470         test    %ebx,%ebx
471         je      noint
472
473         cmp     $1,%ebx
474         je      int1
475         cmp     $2,%ebx
476         je      int2
477
478         mov     -12(itmp2),%ebp
479 int2:   
480         mov     -8(itmp2),%esi
481 int1:   
482         mov     -4(itmp2),%edi
483
484         shl     $2,%ebx                     /* multiply by 4 bytes                */
485         sub     %ebx,itmp2
486                 
487 noint:
488         mov     FltSave(itmp3),%ebx         /* %ecx = saved flt register count    */
489         test    %ebx,%ebx
490         je      noflt
491
492         cmp     $1,%ebx
493         je      flt1
494         cmp     $2,%ebx
495         je      flt2
496         cmp     $3,%ebx
497         je      flt3
498                 
499         fldl    -32(itmp2)
500         fstp    %st(1)
501 flt3:
502         fldl    -24(itmp2)
503         fstp    %st(2)
504 flt2:
505         fldl    -16(itmp2)
506         fstp    %st(3)
507 flt1:
508         fldl    -8(itmp2)
509         fstp    %st(4)
510                 
511 noflt:
512                                             /* exception pointer is still set     */
513         pop     xpc                         /* the new xpc is return address      */
514         sub     $2,xpc                      /* subtract 2-bytes for call          */
515
516 #if 0
517         mov     $1,%edi                     /* set indent flag                    */
518 #endif
519
520         jmp     L_asm_handle_exception_stack_loop
521                 
522
523 /* asm_wrapper_patcher *********************************************************
524
525    XXX
526
527    Stack layout:
528      20   return address
529      16   pointer to virtual java_objectheader
530      12   last byte of machine code (xmcode)
531       8   machine code (which is patched back later)
532       4   unresolved field reference
533       0   patcher function pointer to call
534
535 *******************************************************************************/
536
537 asm_wrapper_patcher:
538         sub     $((2+4)*4+sizestackframeinfo),sp /* create stack frame            */
539
540         mov     itmp1,(0+4)*4(sp)           /* save itmp1 and itmp2               */
541         mov     itmp2,(1+4)*4(sp)           /* may be used by some instructions   */
542
543         mov     sp,itmp1                    /* create stackframe info             */
544         add     $((2+4)*4),itmp1
545         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
546         movl    $0,1*4(sp)                  /* if pv is NULL, use findmethod      */
547         mov     sp,itmp2
548         add     $((6+2+4)*4+sizestackframeinfo),itmp2
549         mov     itmp2,2*4(sp)
550         mov     ((5+2+4)*4+sizestackframeinfo)(sp),itmp3
551         mov     itmp3,3*4(sp)
552         call    stacktrace_create_inline_stackframeinfo
553
554         mov     sp,itmp1                    /* pass stack pointer                 */
555         add     $((1+2+4)*4+sizestackframeinfo),itmp1  /* skip function pointer   */
556         mov     itmp1,0*4(sp)
557         mov     (0+2+4)*4+sizestackframeinfo(sp),itmp1 /* get function pointer    */
558         call    *itmp1                      /* call the patcher function          */
559         mov     v0,1*4(sp)                  /* save return value                  */
560
561         mov     sp,itmp1                    /* remove stackframe info             */
562         add     $((2+4)*4),itmp1
563         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
564         call    stacktrace_remove_stackframeinfo
565
566         mov     (0+4)*4(sp),itmp1           /* restore itmp1 and itmp2            */
567         mov     (1+4)*4(sp),itmp2           /* may be used by some instructions   */
568         mov     1*4(sp),itmp3               /* restore return value               */
569
570         add     $((5+2+4)*4+sizestackframeinfo),sp /* remove stack frame, keep ra */
571         test    itmp3,itmp3                 /* exception thrown?                  */
572         jz      L_asm_wrapper_patcher_exception
573         ret                                 /* call new patched code              */
574
575 L_asm_wrapper_patcher_exception:
576 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
577         call    builtin_asm_get_exceptionptrptr
578         mov     v0,itmp2
579 #else
580         lea     _exceptionptr,itmp2
581 #endif
582         mov     (itmp2),xptr                /* get the exception pointer          */
583         movl    $0,(itmp2)                  /* clear the exception pointer        */
584
585         pop     xpc                         /* get and remove return address      */
586         jmp     asm_handle_exception
587
588
589 /************************ function asm_builtin_x2x *****************************
590 *                                                                              *
591 *   Wrapper functions for corner cases                                         *
592 *                                                                              *
593 *******************************************************************************/
594
595 asm_builtin_f2i:
596         sub     $4,%esp
597         fsts    (%esp)
598         call    builtin_f2i
599         add     $4,%esp
600         ret
601
602 asm_builtin_d2i:
603         sub     $8,%esp
604         fstl    (%esp)
605         call    builtin_d2i
606         add     $8,%esp
607         ret
608
609 asm_builtin_f2l:
610         sub     $4,%esp
611         fsts    (%esp)
612         call    builtin_f2l
613         add     $4,%esp
614         ret
615
616 asm_builtin_d2l:
617         sub     $8,%esp
618         fstl    (%esp)
619         call    builtin_d2l
620         add     $8,%esp
621         ret
622
623
624 /******************* function asm_initialize_thread_stack **********************
625 *                                                                              *
626 * initialized a thread stack                                                   *
627 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
628 *                                                                              *
629 *******************************************************************************/
630
631 asm_initialize_thread_stack:
632                 mov             8(%esp),%eax            /* (to)->stackEnd                     */
633                 sub             $36,%eax                /* 4 bytes * 8 regs + 4 bytes func    */
634                                 
635                 xor             %edx,%edx
636                 mov             %edx,0(%eax)
637                 mov             %edx,4(%eax)
638                 mov             %edx,8(%eax)
639                 mov             %edx,12(%eax)
640                 mov             %edx,16(%eax)
641                 mov             %edx,20(%eax)
642                 mov     %edx,24(%eax)
643                 mov     %edx,28(%eax)
644                                 
645                 mov     4(%esp),%edx            /* save (u1*) (func)                  */
646                 mov     %edx,32(%eax)
647
648                 ret                             /* return restorepoint in %eax        */
649
650
651 /******************* function asm_perform_threadswitch *************************
652 *                                                                              *
653 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
654 *                                                                              *
655 *   performs a threadswitch                                                    *
656 *                                                                              *
657 *******************************************************************************/
658
659 asm_perform_threadswitch:
660         sub     $36,%esp
661            
662         mov     %eax,0(%esp)
663         mov     %ecx,4(%esp)
664         mov     %edx,8(%esp)
665         mov     %ebx,12(%esp)
666         mov     %esp,16(%esp)
667         mov     %ebp,20(%esp)
668         mov     %esi,24(%esp)
669         mov     %edi,28(%esp)
670            
671         mov     36(%esp),%eax         /* save current return address              */
672         mov     %eax,32(%esp)
673            
674         mov     40(%esp),%eax         /* first argument **from                    */
675         mov     %esp,0(%eax)
676            
677         mov     48(%esp),%eax         /* third argument **stackTop                */
678         mov     %esp,0(%eax)
679            
680         mov     44(%esp),%eax         /* second argument **to                     */
681         mov     0(%eax),%esp          /* load new stack pointer                   */
682            
683         mov     0(%esp),%eax
684         mov     4(%esp),%ecx
685         mov     8(%esp),%edx
686         mov     12(%esp),%ebx
687                                       /* skip stack pointer                       */
688         mov     20(%esp),%ebp
689         mov     24(%esp),%esi
690         mov     28(%esp),%edi
691            
692         add     $32,%esp              /* leave return address on stack            */
693         ret
694                 
695
696 /********************* function asm_switchstackandcall *************************
697 *                                                                              *
698 *  int asm_switchstackandcall (void *stack, void *func, void **stacktopsave,   *
699 *                                      void *p);                                       *
700 *                                                                              *
701 *   Switches to a new stack, calls a function and switches back.               *
702 *       a0      new stack pointer                                              *
703 *       a1      function pointer                                               *
704 *               a2              pointer to variable where stack top should be stored           *
705 *       a3      pointer to user data, is passed to the function                *
706 *                                                                              *
707 *******************************************************************************/
708
709 asm_switchstackandcall:
710         mov     4(%esp),%edx          /* first argument *stack                    */
711         sub     $8,%edx               /* allocate new stack                       */
712
713         mov     (%esp),%eax           /* save return address on new stack         */
714         mov     %eax,(%edx)
715
716         mov     %esp,4(%edx)          /* save old stack pointer on new stack      */
717
718         mov     12(%esp),%eax         /* third argument **stacktopsave            */
719         mov     %esp,(%eax)           /* save old stack pointer to variable       */
720
721         mov     8(%esp),%eax          /* load function pointer                    */
722         mov     16(%esp),%ecx         /* fourth argument *p                       */
723         
724         mov     %edx,%esp             /* switch to new stack                      */
725
726         sub     $4,%esp
727         mov     %ecx,0(%esp)          /* pass pointer                             */
728         call    *%eax                 /* and call function                        */
729         add     $4,%esp
730
731         mov     (%esp),%edx           /* load return address                      */
732         mov     4(%esp),%esp          /* switch to old stack                      */
733         mov     %edx,(%esp)
734         ret
735
736                 
737 asm_getclassvalues_atomic:
738 _crit_restart2:
739         mov     4(%esp),%ecx        /* super */
740         mov     8(%esp),%edx        /* sub */
741 _crit_begin2:
742         mov     offbaseval(%ecx),%eax
743         mov     offdiffval(%ecx),%ecx
744         mov     offbaseval(%edx),%edx
745 _crit_end2:
746         push    %ebx
747         mov     16(%esp),%ebx      /* out */
748         mov     %eax,offcast_super_baseval(%ebx)
749         mov     %ecx,offcast_super_diffval(%ebx)
750         mov     %edx,offcast_sub_baseval(%ebx)
751         pop     %ebx
752         ret
753
754         .data
755
756 asm_criticalsections:
757 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
758 #if 0
759         .long   _crit_begin1
760         .long   _crit_end1
761         .long   _crit_restart1
762 #endif
763         .long   _crit_begin2
764         .long   _crit_end2
765         .long   _crit_restart2
766 #endif
767         .long 0
768
769
770 /*
771  * These are local overrides for various environment variables in Emacs.
772  * Please do not remove this and leave it at the end of the file, where
773  * Emacs will automagically detect them.
774  * ---------------------------------------------------------------------
775  * Local variables:
776  * mode: asm
777  * indent-tabs-mode: t
778  * c-basic-offset: 4
779  * tab-width: 4
780  * End:
781  */