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