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