* New, simpler, more generic stacktrace system
[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 2999 2005-07-12 11:20:34Z twisti $
34
35 */
36
37
38 #include "config.h"
39 #include "vm/jit/i386/offsets.h"
40 #include "vm/jit/i386/asmoffsets.h"
41
42
43 /* define it like the risc way */
44
45 #define v0       %eax
46
47 #define sp       %esp
48
49 #define itmp1    %eax
50 #define itmp2    %ecx
51 #define itmp3    %edx
52
53 #define itmp1b   %al
54 #define itmp2b   %cl
55 #define itmp3b   %dl
56
57 #define xptr     itmp1
58 #define xpc      itmp2
59
60
61         .text
62
63
64 /********************* exported functions and variables ***********************/
65
66         .globl asm_calljavafunction
67         .globl asm_calljavafunction_int
68
69         .globl asm_calljavafunction2
70         .globl asm_calljavafunction2int
71         .globl asm_calljavafunction2long
72         .globl asm_calljavafunction2float
73         .globl asm_calljavafunction2double
74
75         .globl asm_call_jit_compiler
76         .globl asm_handle_nat_exception
77         .globl asm_handle_exception
78
79         .globl asm_wrapper_patcher
80
81         .globl asm_builtin_f2i
82         .globl asm_builtin_f2l
83         .globl asm_builtin_d2i
84         .globl asm_builtin_d2l
85
86         .globl asm_perform_threadswitch
87         .globl asm_initialize_thread_stack
88         .globl asm_switchstackandcall
89         .globl asm_criticalsections
90         .globl asm_getclassvalues_atomic
91
92
93 /********************* function asm_calljavafunction ***************************
94 *                                                                              *
95 *   This function calls a Java-method (which possibly needs compilation)       *
96 *   with up to 4 address parameters.                                           *
97 *                                                                              *
98 *   This functions calls the JIT-compiler which eventually translates the      *
99 *   method into machine code.                                                  *
100 *                                                                              *
101 *   C-prototype:                                                               *
102 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
103 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
104 *                                                                              *
105 *******************************************************************************/
106
107 call_name:
108         .align  8
109
110         .long   0                         /* catch type all                       */
111         .long   calljava_xhandler         /* handler pc                           */
112         .long   calljava_xhandler         /* end pc                               */
113         .long   asm_calljavafunction      /* start pc                             */
114         .long   1                         /* extable size                         */
115         .long   0                         /* line number table start              */
116         .long   0                         /* line number table size               */
117         .long   0                         /* fltsave                              */
118         .long   0                         /* intsave                              */
119         .long   0                         /* isleaf                               */
120         .long   0                         /* IsSync                               */
121         .long   32                        /* frame size                           */
122         .long   0                         /* method pointer (pointer to name)     */
123
124 asm_calljavafunction:
125 asm_calljavafunction_int:
126         push    %ebp                      /* allocate stack space                 */
127         mov     %esp, %ebp
128
129         push    %ebx                      /* save registers                       */
130         push    %esi
131         push    %edi
132
133
134         sub             $16,%esp                                        /* 4 adress parameters * 4 Bytes */
135         mov     24(%ebp),%eax                           /* copy adress parameters to new block */
136         mov     %eax,12(%esp)
137                 
138         mov     20(%ebp),%eax
139         mov     %eax,8(%esp)
140
141         mov     16(%ebp),%eax
142         mov     %eax,4(%esp)
143
144         mov     12(%ebp),%eax
145         mov     %eax,(%esp)
146                 
147         mov     8(%ebp),%eax              /* move function pointer to %eax        */
148
149         lea     asm_call_jit_compiler,%edx 
150         call    *%edx                     /* call JIT compiler                    */
151
152         add     $16,%esp
153         pop     %edi                      /* restore registers                    */
154         pop     %esi
155         pop     %ebx
156         leave
157         ret
158
159 calljava_xhandler:
160         push    %eax                      /* pass exception pointer               */
161         call    builtin_throw_exception
162         add     $4,%esp
163
164         add     $16,%esp
165         pop     %edi                      /* restore registers                    */
166         pop     %esi
167         pop     %ebx
168         leave
169         xor     %eax,%eax                 /* return NULL                          */
170         ret
171
172
173 /********************* function asm_calljavafunction ***************************
174 *                                                                              *
175 *   This function calls a Java-method (which possibly needs compilation)       *
176 *   with up to 4 address parameters.                                           *
177 *                                                                              *
178 *   This functions calls the JIT-compiler which eventually translates the      *
179 *   method into machine code.                                                  *
180 *                                                                              *
181 *   C-prototype:                                                               *
182 *    javaobject_header *asm_calljavafunction2(methodinfo *m,                   *
183 *         u4 count, u4 size, void *callblock);                                 *
184 *                                                                              *
185 *******************************************************************************/
186
187 call_name2:
188         .align  8
189
190         .long   0                         /* catch type all                       */
191         .long   calljava_xhandler2        /* handler pc                           */
192         .long   calljava_xhandler2        /* end pc                               */
193         .long   asm_calljavafunction2     /* start pc                             */
194         .long   1                         /* extable size                         */
195         .long   0                         /* line number table start              */
196         .long   0                         /* line number table size               */
197         .long   0                         /* fltsave                              */
198         .long   0                         /* intsave                              */
199         .long   0                         /* isleaf                               */
200         .long   0                         /* IsSync                               */
201         .long   32                        /* frame size                           */
202         .long   0                         /* method pointer (pointer to name)     */
203
204 asm_calljavafunction2:
205 asm_calljavafunction2int:
206 asm_calljavafunction2long:
207 asm_calljavafunction2float:
208 asm_calljavafunction2double:
209         push    %ebp
210         mov     %esp,%ebp                 /* save stackptr                        */
211
212         push    %ebx                      /* save registers                       */
213         push    %esi
214         push    %edi
215
216         mov     20(%ebp),%eax             /* pointer to arg block (4(push)+4(return)+4+4+4)*/
217         mov     12(%ebp),%ecx             /* arg count            (4(push)+4(return)+4     */
218         test    %ecx,%ecx                 /* maybe we have no args                */
219         jle     calljava_copydone
220
221                 mov             %ecx,%edx                        /* calculate stack size                 */
222                 xor             %esi,%esi
223                 mov             %eax,%edi                        /* save pointer to arg block */
224 calljava_calcstacksize:
225                 mov             offjniitemtype(%eax),%ebx
226                 test    $1,%ebx                                 /* Two Word Type? */
227                 jz              calljava_onewordtype
228                 add             $4,%esi
229 calljava_onewordtype:
230                 add             $4,%esi
231                 sub             $1,%edx
232                 test    %edx,%edx                               /* any args left ?*/
233                 jz              calljava_setstack
234                 add     $sizejniblock,%eax      /* goto next argument block             */
235                 jmp             calljava_calcstacksize
236                 
237 calljava_setstack:                              
238                 mov             %edi,%eax                        /* restore pointer to arg block */
239         sub     %esi,%esp                 /* stack frame for arguments            */
240         mov     %esp,%edi
241
242 calljava_copyloop:
243             mov     offjniitem(%eax),%edx   /* copy 4 Byte of Argument */
244             mov     %edx,(%edi)
245                 add             $4,%edi                                 /* increase sp to next argument         */
246                 mov             offjniitemtype(%eax),%ebx /* type -> ebx */
247                 test    $1,%ebx                                 /* Two Word Type? */
248                 jz              calljava_copynext
249             mov     offjniitem+4(%eax),%edx /* copy upper 4 Byte of 2 Word Type */  
250                 mov     %edx,(%edi)                     
251                 add             $4,%edi                                 /* increase sp to next argument         */
252 calljava_copynext:              
253         sub     $1,%ecx                   /* are there any args left?             */
254         test    %ecx,%ecx
255         jle     calljava_copydone
256
257         add     $sizejniblock,%eax        /* goto next argument block             */
258         jmp     calljava_copyloop
259
260 calljava_copydone:
261         mov     8(%ebp),%eax              /* move function pointer to %eax        */
262
263         lea     asm_call_jit_compiler,%edx 
264         call    *%edx                     /* call JIT compiler                    */
265         
266 calljava_return2:
267         add     %esi,%esp                 /* remove arg stack frame               */
268         pop     %edi                      /* restore registers                    */
269         pop     %esi
270         pop     %ebx
271         leave
272         ret
273
274 calljava_xhandler2:
275         push    %eax                      /* pass exception pointer               */
276         call    builtin_throw_exception
277         add     $4,%esp
278     
279         add     %esi,%esp                 /* remove arg stack frame               */
280         pop     %edi                      /* restore registers                    */
281         pop     %esi
282         pop     %ebx
283         leave
284         xor     %eax,%eax                 /* return NULL                          */
285         ret
286
287
288 /****************** function asm_call_jit_compiler *****************************
289 *                                                                              *
290 *   invokes the compiler for untranslated JavaVM methods.                      *
291 *                                                                              *
292 *   Register R0 contains a pointer to the method info structure (prepared      *
293 *   by createcompilerstub). Using the return address in R26 and the            *
294 *   offset in the LDA instruction or using the value in methodptr R28 the      *
295 *   patching address for storing the method address can be computed:           *
296 *                                                                              *
297 *   method address was either loaded using                                     *
298 *                                                                              *
299 *   i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special       *
300 *   i386_call_reg(REG_ITMP2)                                                   *
301 *                                                                              *
302 *   or                                                                         *
303 *                                                                              *
304 *   i386_mov_membase_reg(REG_SP, 0, REG_ITMP1)    ; invokevirtual/interface    *
305 *   i386_mov_membase_reg(REG_ITMP1, OFFSET(, vftbl), REG_ITMP2)                *
306 *   i386_mov_membase_reg(REG_ITMP2, OFFSET(vftbl, table[0]) + \                *
307 *       sizeof(methodptr) * m->vftblindex, REG_ITMP1)                          *
308 *   i386_call_reg(REG_ITMP1)                                                   *
309 *                                                                              *
310 *   in the static case the method pointer can be computed using the            *
311 *   return address and the lda function following the jmp instruction          *
312 *                                                                              *
313 *******************************************************************************/
314
315 asm_call_jit_compiler:
316         push    %ebx                /* save register                              */
317     push    %ebp
318                         
319         mov     2*4(%esp),%ebp      /* get return address (2 push)                */
320         mov     -1(%ebp),%bl        /* get function code                          */
321         cmp     $0xd1,%bl           /* called with `call *REG_ITMP2' (%ecx)?      */
322         jne             L_not_static_special
323
324         sub     $6,%ebp             /* calculate address of immediate             */
325         jmp             L_call_jit_compile
326                 
327 L_not_static_special:
328         cmp     $0xd0,%bl           /* called with `call *REG_ITMP1' (%eax)       */
329         jne             L_not_virtual_interface
330         
331         sub     $6,%ebp             /* calculate address of offset                */
332         mov     (%ebp),%ebp         /* get offset                                 */
333         add     itmp2,%ebp          /* add base address to get method address     */
334         jmp             L_call_jit_compile
335
336 L_not_virtual_interface:        /* a call from asm_calljavafunction           */
337         xor     %ebp,%ebp
338                 
339 L_call_jit_compile:
340         push    %ebp                /* save address for method pointer            */
341
342         push    %eax                /* push methodpointer on stack                */
343         call    jit_compile
344         add     $4,%esp
345
346         pop     %ebp                /* restore address for method pointer         */
347
348         test    %eax,%eax           /* check for exception                        */
349         je      L_asm_call_jit_compiler_exception
350
351         test    %ebp,%ebp           /* is address == 0 (asm_calljavafunction)     */
352         je              L_call_method
353         
354         mov     %eax,(%ebp)         /* and now save the new pointer               */
355
356 L_call_method:
357         pop     %ebp                /* restore registers                          */
358         pop     %ebx
359                 
360         jmp             *%eax               /* ...and now call the new method             */
361
362 L_asm_call_jit_compiler_exception:
363         pop     %ebp                /* restore registers                          */
364         pop     %ebx
365
366 #if 0
367 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
368         call    builtin_asm_get_exceptionptrptr
369         mov     v0,itmp2
370 #else
371         lea     _exceptionptr,itmp2
372 #endif
373         mov     (itmp2),xptr        /* get the exception pointer                  */
374         movl    $0,(itmp2)          /* clear the exception pointer                */
375
376         sub     $(5*4+sizestackframeinfo),sp
377         mov     xptr,4*4(sp)                /* save exception pointer             */
378
379         mov     sp,itmp1                    /* create stackframe info             */
380         add     $(5*4),itmp1
381         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
382         movl    $0,1*4(sp)                  /* if pv is NULL, use findmethod      */
383         mov     sp,itmp2
384         add     $(6*4+sizestackframeinfo),itmp2
385         mov     itmp2,2*4(sp)
386         mov     (5*4+sizestackframeinfo)(sp),itmp3
387         mov     itmp3,3*4(sp)
388         call    stacktrace_create_inline_stackframeinfo
389
390         mov     4*4(sp),itmp1               /* fill in stacktrace                 */
391         mov     itmp1,0*4(sp)
392         call    stacktrace_call_fillInStackTrace
393         
394         mov     sp,itmp1                    /* remove stackframe info             */
395         add     $(5*4),itmp1
396         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
397         call    stacktrace_remove_stackframeinfo
398
399         mov     4*4(sp),xptr                /* restore exception pointer          */
400         add     $(5*4+sizestackframeinfo),sp
401 #endif
402         sub     $(4*4),sp
403
404         movl    $0,0*4(sp)                  /* we don't have pv handy             */
405         mov     sp,itmp1                    /* pass java sp                       */
406         add     $((1+5)*4),itmp1            /* also skip ra                       */
407         mov     itmp1,1*4(sp)
408         mov     5*4(sp),itmp2               /* pass java ra                       */
409         mov     itmp2,2*4(sp)
410         mov     itmp2,3*4(sp)               /* xpc is equal to ra                 */
411         call    stacktrace_extern_fillInStackTrace
412
413         add     $(4*4),sp
414
415         pop     xpc                         /* get return address                 */
416         sub     $2,xpc                      /* faulting address is ra - 2         */
417         jmp     asm_handle_exception
418
419
420 /********************* function asm_handle_exception ***************************
421 *                                                                              *
422 *   This function handles an exception. It does not use the usual calling      *
423 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
424 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
425 *   the local exception table for a handler. If no one is found, it unwinds    *
426 *   stacks and continues searching the callers.                                *
427 *                                                                              *
428 *   void asm_handle_exception (exceptionptr, exceptionpc);                     *
429 *                                                                              *
430 *******************************************************************************/
431
432 asm_handle_nat_exception:
433         add     $4,%esp                    /* clear return address of native stub */
434                 
435 asm_handle_exception:
436 asm_handle_exception_loop:
437                 push    %ebp
438                 mov     %esp,%ebp
439         
440                 push    %eax                                            /* save exception pointer         */
441                 push    %ecx                        /* save exception pc              */
442
443                 call    codegen_findmethod          /* get the data segment ptr       */
444                 mov     %eax,%edx
445                         
446                 mov     -4(%ebp),%eax
447                 mov     -8(%ebp),%ecx               /* could be changed in findmethod */
448
449                 push    %edx                                            /* save data segment pointer      */
450                 push    %ebx
451                 push    %esi
452                 push    %edi
453                 
454 ex_stack_loop:
455                 sub     $20,%esp
456                 mov     %eax,(%esp)                                     /* exception pointer              */
457                 mov     MethodPointer(%edx),%eax        /* method pointer                 */
458                 mov     %eax,4(%esp)
459                 mov     %ecx,8(%esp)                            /* exception pc                   */
460                 movl    $0,12(%esp)                 /* line number                    */
461                 movl    $1,16(%esp)                                     /* set no unwind flag             */
462                 call    builtin_trace_exception
463                 add     $20,%esp
464                 mov     -12(%ebp),%esi                          /* %esi = data segment pointer    */
465                 mov     ExTableSize(%esi),%ecx          /* %ecx = exception table size    */
466                 test    %ecx,%ecx                                       /* if empty table skip            */
467                 je      empty_table
468
469                 lea             ExTableStart(%esi),%edi         /* %edi = start of exception table*/
470                 mov     -4(%ebp),%eax               /* get xptr                       */
471                 
472 ex_table_loop:
473                 mov     -8(%ebp),%edx                           /* get xpc                        */
474
475                 mov     ExStartPC(%edi),%ebx            /* %ebx = exception start pc      */
476                 cmp     %edx,%ebx                                       /* %ebx = (startpc <= xpc)        */
477                 jg      ex_table_cont                           /* if (false) continue            */
478                 mov     ExEndPC(%edi),%ebx                      /* %ebx = exception end pc        */
479                 cmp     %ebx,%edx                                       /* %ebx = (xpc < endpc)           */
480                 jge     ex_table_cont                           /* if (false) continue            */
481                 mov     ExCatchType(%edi),%ebx          /* arg1 = exception catch type    */
482                 test    %ebx,%ebx                                       /* NULL catches everything        */
483                 je      ex_handle_it
484
485         cmpl    $0,offclassloaded(%ebx)     /* check if class is loaded           */
486         jne     L_class_loaded
487
488         sub     $3*4,%esp
489         mov     %eax,1*4(%esp)              /* save not callee saved regs         */
490         mov     %ecx,2*4(%esp)
491
492         mov     %ebx,0*4(%esp)              /* exception class is argument        */
493         call    load_class_bootstrap
494
495         mov     0*4(%esp),%ebx
496         mov     1*4(%esp),%eax
497         mov     2*4(%esp),%ecx
498         add     $3*4,%esp
499
500 L_class_loaded:
501         cmpl    $0,offclasslinked(%ebx)
502         jne     L_class_linked
503
504         sub     $3*4,%esp
505         mov     %eax,1*4(%esp)              /* save not callee saved regs         */
506         mov     %ecx,2*4(%esp)
507
508         mov     %ebx,0*4(%esp)              /* exception class is argument        */
509         call    link_class
510
511         mov     0*4(%esp),%ebx
512         mov     1*4(%esp),%eax
513         mov     2*4(%esp),%ecx
514         add     $3*4,%esp
515
516 L_class_linked:
517 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
518         push    %ebx
519
520 _crit_restart1:
521         mov     0(%esp),%ebx
522 #endif
523                 
524 _crit_begin1:
525         mov     offobjvftbl(%eax),%esi          /* %esi = vftblptr(xptr)              */
526         mov     offclassvftbl(%ebx),%ebx    /* %ebx = vftblptr(catchtype) class (not obj) */
527         mov     offbaseval(%esi),%esi           /* %esi = baseval(xptr)               */
528         mov     offbaseval(%ebx),%edx           /* %edx = baseval(catchtype)          */
529         mov     offdiffval(%ebx),%ebx           /* %ebx = diffval(catchtype)          */
530 _crit_end1:
531         sub     %edx,%esi                                       /* %esi = baseval(xptr) - baseval(catchtype) */
532
533 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
534         add     $4,%esp
535 #endif
536         
537         cmp     %ebx,%esi                                       /* xptr is instanceof catchtype       */
538         ja      ex_table_cont
539                 
540 ex_handle_it:
541                 mov     ExHandlerPC(%edi),%edx
542                 
543                 pop     %edi                        /* restore registers              */
544                 pop     %esi
545                 pop     %ebx
546         add     $8,%esp                     /* suck %ecx, %edx                */
547         pop     %eax                        /* restore xptr                   */
548
549                 leave
550                 jmp             *%edx                       /* jump to exception handler      */
551
552 ex_table_cont:
553                 lea     ExEntrySize(%edi),%edi
554                 dec     %ecx
555                 test    %ecx,%ecx
556                 jg      ex_table_loop
557                 
558 empty_table:
559         pop     %edi
560         pop     %esi
561         pop     %ebx
562         pop     %edx                        /* restore data segment pointer   */
563         pop     %ecx
564         pop     %eax
565         pop     %ebp
566
567         push    %eax                        /* save exception pointer         */
568         
569 ex_already_cleared:
570                 mov     IsSync(%edx),%eax                       /* %eax = SyncOffset              */
571                 test    %eax,%eax                                       /* if zero no monitorexit         */
572                 je      no_monitor_exit
573
574 #if defined(USE_THREADS)
575         add     %esp,%eax
576         mov     (%eax),%eax               /* we have the xptr on the stack (+4-4=0)  */
577         push    %edx                        /* save regs                      */
578         push    %eax
579                 call    builtin_monitorexit
580                 add     $4,%esp
581         pop     %edx                        /* restore regs                   */
582 #endif
583
584 no_monitor_exit:
585         mov     %esp,%eax
586         add     FrameSize(%edx),%eax        /* %eax = frame size              */
587         add     $4,%eax                     /* we have the xptr on the stack  */
588         
589                 mov     IntSave(%edx),%ecx          /* %ecx = saved int register count*/
590                 test    %ecx,%ecx
591                 je      noint
592                 cmp     $1,%ecx
593                 je      int1
594                 cmp     $2,%ecx
595                 je      int2
596                 cmp     $3,%ecx
597                 je      int3
598
599 int4:   
600                 mov     -16(%eax),%ebx
601
602 int3:   
603                 mov     -12(%eax),%ebp
604
605 int2:   
606                 mov     -8(%eax),%esi
607
608 int1:   
609                 mov     -4(%eax),%edi
610
611                 shl     $2,%ecx                                         /* multiply by 4 bytes             */
612                 sub     %ecx,%eax
613                 
614 noint:
615                 mov     FltSave(%edx),%ecx                      /* %ecx = saved flt register count */
616                 test    %ecx,%ecx
617                 je      noflt
618                 cmp     $1,%ecx
619                 je      flt1
620                 cmp     $2,%ecx
621                 je      flt2
622                 cmp     $3,%ecx
623                 je      flt3
624                 
625 flt4:   
626                 fldl    -32(%eax)
627                 fstp    %st(1)
628
629 flt3:   
630                 fldl    -24(%eax)
631                 fstp    %st(2)
632                 
633 flt2:   
634                 fldl    -16(%eax)
635                 fstp    %st(3)
636                 
637 flt1:   
638                 fldl    -8(%eax)
639                 fstp    %st(4)
640                 
641 noflt:
642         pop     %eax                        /* restore exception pointer      */
643         
644         mov     FrameSize(%edx),%ecx        /* %ecx = frame size              */
645         add     %ecx,%esp                   /* unwind stack                   */
646         
647                 pop     %ecx                        /* the new xpc is return address  */
648                 sub     $2,%ecx                                         /* -2 -> call */
649                 
650                 jmp             asm_handle_exception_loop
651                 
652
653 /* asm_wrapper_patcher *********************************************************
654
655    XXX
656
657    Stack layout:
658      20   return address
659      16   pointer to virtual java_objectheader
660      12   last byte of machine code (xmcode)
661       8   machine code (which is patched back later)
662       4   unresolved field reference
663       0   patcher function pointer to call
664
665 *******************************************************************************/
666
667 asm_wrapper_patcher:
668         sub     $((2+4)*4+sizestackframeinfo),sp /* create stack frame            */
669
670         mov     itmp1,(0+4)*4(sp)           /* save itmp1 and itmp2               */
671         mov     itmp2,(1+4)*4(sp)           /* may be used by some instructions   */
672
673         mov     sp,itmp1                    /* create stackframe info             */
674         add     $((2+4)*4),itmp1
675         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
676         movl    $0,1*4(sp)                  /* if pv is NULL, use findmethod      */
677         mov     sp,itmp2
678         add     $((6+2+4)*4+sizestackframeinfo),itmp2
679         mov     itmp2,2*4(sp)
680         mov     ((5+2+4)*4+sizestackframeinfo)(sp),itmp3
681         mov     itmp3,3*4(sp)
682         call    stacktrace_create_inline_stackframeinfo
683
684         mov     sp,itmp1                    /* pass stack pointer                 */
685         add     $((1+2+4)*4+sizestackframeinfo),itmp1  /* skip function pointer   */
686         mov     itmp1,0*4(sp)
687         mov     (0+2+4)*4+sizestackframeinfo(sp),itmp1 /* get function pointer    */
688         call    *itmp1                      /* call the patcher function          */
689         mov     v0,1*4(sp)                  /* save return value                  */
690
691         mov     sp,itmp1                    /* remove stackframe info             */
692         add     $((2+4)*4),itmp1
693         mov     itmp1,0*4(sp)               /* stackframeinfo pointer             */
694         call    stacktrace_remove_stackframeinfo
695
696         mov     (0+4)*4(sp),itmp1           /* restore itmp1 and itmp2            */
697         mov     (1+4)*4(sp),itmp2           /* may be used by some instructions   */
698         mov     1*4(sp),itmp3               /* restore return value               */
699
700         add     $((5+2+4)*4+sizestackframeinfo),sp /* remove stack frame, keep ra */
701         test    itmp3,itmp3                 /* exception thrown?                  */
702         jz      L_asm_wrapper_patcher_exception
703         ret                                 /* call new patched code              */
704
705 L_asm_wrapper_patcher_exception:
706 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
707         call    builtin_asm_get_exceptionptrptr
708         mov     v0,itmp2
709 #else
710         lea     _exceptionptr,itmp2
711 #endif
712         mov     (itmp2),xptr                /* get the exception pointer          */
713         movl    $0,(itmp2)                  /* clear the exception pointer        */
714
715         pop     xpc                         /* get and remove return address      */
716         jmp     asm_handle_exception
717
718
719 /************************ function asm_builtin_x2x *****************************
720 *                                                                              *
721 *   Wrapper functions for corner cases                                         *
722 *                                                                              *
723 *******************************************************************************/
724
725 asm_builtin_f2i:
726         sub     $4,%esp
727         fsts    (%esp)
728         call    builtin_f2i
729         add     $4,%esp
730         ret
731
732 asm_builtin_d2i:
733         sub     $8,%esp
734         fstl    (%esp)
735         call    builtin_d2i
736         add     $8,%esp
737         ret
738
739 asm_builtin_f2l:
740         sub     $4,%esp
741         fsts    (%esp)
742         call    builtin_f2l
743         add     $4,%esp
744         ret
745
746 asm_builtin_d2l:
747         sub     $8,%esp
748         fstl    (%esp)
749         call    builtin_d2l
750         add     $8,%esp
751         ret
752
753
754 /******************* function asm_initialize_thread_stack **********************
755 *                                                                              *
756 * initialized a thread stack                                                   *
757 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
758 *                                                                              *
759 *******************************************************************************/
760
761 asm_initialize_thread_stack:
762                 mov             8(%esp),%eax            /* (to)->stackEnd                     */
763                 sub             $36,%eax                /* 4 bytes * 8 regs + 4 bytes func    */
764                                 
765                 xor             %edx,%edx
766                 mov             %edx,0(%eax)
767                 mov             %edx,4(%eax)
768                 mov             %edx,8(%eax)
769                 mov             %edx,12(%eax)
770                 mov             %edx,16(%eax)
771                 mov             %edx,20(%eax)
772                 mov     %edx,24(%eax)
773                 mov     %edx,28(%eax)
774                                 
775                 mov     4(%esp),%edx            /* save (u1*) (func)                  */
776                 mov     %edx,32(%eax)
777
778                 ret                             /* return restorepoint in %eax        */
779
780
781 /******************* function asm_perform_threadswitch *************************
782 *                                                                              *
783 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
784 *                                                                              *
785 *   performs a threadswitch                                                    *
786 *                                                                              *
787 *******************************************************************************/
788
789 asm_perform_threadswitch:
790         sub     $36,%esp
791            
792         mov     %eax,0(%esp)
793         mov     %ecx,4(%esp)
794         mov     %edx,8(%esp)
795         mov     %ebx,12(%esp)
796         mov     %esp,16(%esp)
797         mov     %ebp,20(%esp)
798         mov     %esi,24(%esp)
799         mov     %edi,28(%esp)
800            
801         mov     36(%esp),%eax         /* save current return address              */
802         mov     %eax,32(%esp)
803            
804         mov     40(%esp),%eax         /* first argument **from                    */
805         mov     %esp,0(%eax)
806            
807         mov     48(%esp),%eax         /* third argument **stackTop                */
808         mov     %esp,0(%eax)
809            
810         mov     44(%esp),%eax         /* second argument **to                     */
811         mov     0(%eax),%esp          /* load new stack pointer                   */
812            
813         mov     0(%esp),%eax
814         mov     4(%esp),%ecx
815         mov     8(%esp),%edx
816         mov     12(%esp),%ebx
817                                       /* skip stack pointer                       */
818         mov     20(%esp),%ebp
819         mov     24(%esp),%esi
820         mov     28(%esp),%edi
821            
822         add     $32,%esp              /* leave return address on stack            */
823         ret
824                 
825
826 /********************* function asm_switchstackandcall *************************
827 *                                                                              *
828 *  int asm_switchstackandcall (void *stack, void *func, void **stacktopsave,   *
829 *                                      void *p);                                       *
830 *                                                                              *
831 *   Switches to a new stack, calls a function and switches back.               *
832 *       a0      new stack pointer                                              *
833 *       a1      function pointer                                               *
834 *               a2              pointer to variable where stack top should be stored           *
835 *       a3      pointer to user data, is passed to the function                *
836 *                                                                              *
837 *******************************************************************************/
838
839 asm_switchstackandcall:
840         mov     4(%esp),%edx          /* first argument *stack                    */
841         sub     $8,%edx               /* allocate new stack                       */
842
843         mov     (%esp),%eax           /* save return address on new stack         */
844         mov     %eax,(%edx)
845
846         mov     %esp,4(%edx)          /* save old stack pointer on new stack      */
847
848         mov     12(%esp),%eax         /* third argument **stacktopsave            */
849         mov     %esp,(%eax)           /* save old stack pointer to variable       */
850
851         mov     8(%esp),%eax          /* load function pointer                    */
852         mov     16(%esp),%ecx         /* fourth argument *p                       */
853         
854         mov     %edx,%esp             /* switch to new stack                      */
855
856         sub     $4,%esp
857         mov     %ecx,0(%esp)          /* pass pointer                             */
858         call    *%eax                 /* and call function                        */
859         add     $4,%esp
860
861         mov     (%esp),%edx           /* load return address                      */
862         mov     4(%esp),%esp          /* switch to old stack                      */
863         mov     %edx,(%esp)
864         ret
865
866                 
867 asm_getclassvalues_atomic:
868 _crit_restart2:
869         mov     4(%esp),%ecx        /* super */
870         mov     8(%esp),%edx        /* sub */
871 _crit_begin2:
872         mov     offbaseval(%ecx),%eax
873         mov     offdiffval(%ecx),%ecx
874         mov     offbaseval(%edx),%edx
875 _crit_end2:
876         push    %ebx
877         mov     16(%esp),%ebx      /* out */
878         mov     %eax,offcast_super_baseval(%ebx)
879         mov     %ecx,offcast_super_diffval(%ebx)
880         mov     %edx,offcast_sub_baseval(%ebx)
881         pop     %ebx
882         ret
883
884         .data
885
886 asm_criticalsections:
887 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
888         .long   _crit_begin1
889         .long   _crit_end1
890         .long   _crit_restart1
891         .long   _crit_begin2
892         .long   _crit_end2
893         .long   _crit_restart2
894 #endif
895         .long 0
896
897
898 /*
899  * These are local overrides for various environment variables in Emacs.
900  * Please do not remove this and leave it at the end of the file, where
901  * Emacs will automagically detect them.
902  * ---------------------------------------------------------------------
903  * Local variables:
904  * mode: asm
905  * indent-tabs-mode: t
906  * c-basic-offset: 4
907  * tab-width: 4
908  * End:
909  */