* Updated header: Added 2006. Changed address of FSF. Changed email
[cacao.git] / src / vm / jit / x86_64 / asmpart.S
1 /* src/vm/jit/x86_64/asmpart.S - Java-C interface functions for x86_64
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:
32
33    $Id: asmpart.S 4357 2006-01-22 23:33:38Z twisti $
34
35 */
36
37
38 #include "config.h"
39
40 #include "md-abi.h"
41 #include "md-asm.h"
42
43 #include "vm/jit/abi.h"
44 #include "vm/jit/x86_64/arch.h"
45 #include "vm/jit/x86_64/offsets.h"
46
47 #include "vm/jit/methodheader.h"
48
49
50         .text
51
52
53 /********************* exported functions and variables ***********************/
54
55         .globl asm_calljavafunction
56         .globl asm_calljavafunction_int
57
58         .globl asm_calljavafunction2
59         .globl asm_calljavafunction2int
60         .globl asm_calljavafunction2long
61         .globl asm_calljavafunction2float
62         .globl asm_calljavafunction2double
63
64         .globl asm_call_jit_compiler
65         .globl asm_handle_exception
66         .globl asm_handle_nat_exception
67
68         .globl asm_wrapper_patcher
69
70         .globl asm_builtin_f2i
71         .globl asm_builtin_f2l
72         .globl asm_builtin_d2i
73         .globl asm_builtin_d2l
74
75         .globl asm_perform_threadswitch
76         .globl asm_initialize_thread_stack
77         .globl asm_switchstackandcall
78         .globl asm_criticalsections
79         .globl asm_getclassvalues_atomic
80
81
82 /********************* function asm_calljavafunction ***************************
83 *                                                                              *
84 *   This function calls a Java-method (which possibly needs compilation)       *
85 *   with up to 4 address parameters.                                           *
86 *                                                                              *
87 *   This functions calls the JIT-compiler which eventually translates the      *
88 *   method into machine code.                                                  *
89 *                                                                              *
90 *   C-prototype:                                                               *
91 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
92 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
93 *                                                                              *
94 *******************************************************************************/
95
96         .align  8
97
98         .quad   0                           /* catch type all                     */
99         .quad   calljava_xhandler           /* handler pc                         */
100         .quad   calljava_xhandler           /* end pc                             */
101         .quad   asm_calljavafunction        /* start pc                           */
102         .long   1                           /* extable size                       */
103         .long   0                                                                                                                         
104         .quad   0                           /* line number table start            */
105         .quad   0                           /* line number table size             */
106         .long   0                                                                                                                         
107         .long   0                           /* fltsave                            */
108         .long   0                           /* intsave                            */
109         .long   0                           /* isleaf                             */
110         .long   0                           /* IsSync                             */
111         .long   8                           /* frame size                         */
112         .quad   0                           /* method pointer (pointer to name)   */
113
114 asm_calljavafunction:
115 asm_calljavafunction_int:
116         sub     $(3*8),sp                   /* keep stack 16-byte aligned         */
117         mov     bp,0*8(sp)
118         mov     %rbx,1*8(sp)                /* %rbx is not a callee saved in CACAO*/
119         mov     a0,itmp1                    /* move function pointer to itmp1     */
120                                                                             /* compilerstub uses this             */
121
122         mov     a1,a0                       /* pass remaining parameters          */
123         mov     a2,a1                                                                                                                   
124         mov     a3,a2
125         mov     a4,a3
126
127         lea     asm_call_jit_compiler,itmp3
128         call    *itmp3                      /* call JIT compiler                  */
129
130 L_asm_calljavafunction_return:
131         mov     0*8(sp),bp
132         mov             1*8(sp),%rbx                /* %rbx is not a callee saved in CACAO*/
133         add     $(3*8),sp                   /* free stack space                   */
134         ret
135
136 calljava_xhandler:
137         mov     xptr,a0                     /* pass exception pointer             */
138         call    builtin_throw_exception
139         xor     v0,v0                       /* return NULL                        */
140         jmp     L_asm_calljavafunction_return
141
142
143 /********************* function asm_calljavafunction ***************************
144 *                                                                              *
145 *   This function calls a Java-method (which possibly needs compilation)       *
146 *   with up to 4 address parameters.                                           *
147 *                                                                              *
148 *   This functions calls the JIT-compiler which eventually translates the      *
149 *   method into machine code.                                                  *
150 *                                                                              *
151 *   C-prototype:                                                               *
152 *    javaobject_header *asm_calljavamethod (methodinfo *m,                     *
153 *         void *arg1, void *arg2, void *arg3, void *arg4);                     *
154 *                                                                              *
155 *******************************************************************************/
156
157         .align  8
158
159         .quad   0                           /* catch type all                     */
160         .quad   calljava_xhandler2          /* handler pc                         */
161         .quad   calljava_xhandler2          /* end pc                             */
162         .quad   asm_calljavafunction2       /* start pc                           */
163         .long   1                           /* extable size                       */
164         .long   0                                                                                                                        
165         .quad   0                           /* line number table  start           */
166         .quad   0                           /* line number table  size            */
167         .long   0                                                                                                                        
168         .long   0                           /* fltsave                            */
169         .long   0                           /* intsave                            */
170         .long   0                           /* isleaf                             */
171         .long   0                           /* IsSync                             */
172         .long   24                          /* frame size                         */
173         .quad   0                           /* method pointer (pointer to name)   */
174
175 asm_calljavafunction2:
176 asm_calljavafunction2int:
177 asm_calljavafunction2long:
178 asm_calljavafunction2float:
179 asm_calljavafunction2double:
180         sub     $(7*8),sp                   /* keep stack 16-byte aligned         */
181         mov     %rbx,0*8(sp)                /* %rbx is not a callee saved in cacao*/
182         mov     s0,1*8(sp)
183         mov     s1,2*8(sp)
184         mov     s2,3*8(sp)
185         mov     s3,4*8(sp)
186         mov     s4,5*8(sp)
187
188         mov     a0,itmp1                    /* move method pointer for compiler   */
189         xor     %rbp,%rbp                   /* set argument stack frame to zero   */
190
191         test    a1,a1                       /* maybe we have no args...           */
192         jle     L_copy_done
193
194         mov     a1,itmp3                    /* arg count                          */
195         mov     a3,itmp2                    /* pointer to arg block               */
196
197         mov     itmp2,%r14                  /* save argument block pointer        */
198         mov     itmp3,%r15                  /* save argument count                */
199
200         sub     $sizejniblock,itmp2         /* initialize pointer (smaller code)  */
201         add     $1,itmp3                    /* initialize argument count          */
202         xor     %r12,%r12                   /* initialize integer argument counter*/
203         xor     %r13,%r13                   /* initialize float argument counter  */
204
205 L_register_copy:
206         add     $sizejniblock,itmp2       /* goto next argument block             */
207         dec     itmp3                     /* argument count - 1                   */
208         jz      L_register_copy_done
209         andb    $0x02,offjniitemtype(itmp2) /* is this a float/double type?       */
210         jnz     L_register_handle_float   /* yes, handle it                       */
211
212         cmp     $INT_ARG_CNT,%r12         /* are we out of integer argument       */
213         je      L_register_copy           /* register? yes, next loop             */
214
215         lea     jumptable_integer,%rbp
216         mov     0(%rbp,%r12,8),%rbx
217         inc     %r12                      /* integer argument counter + 1         */
218         jmp     *%rbx
219
220 L_register_handle_float:
221         cmp     $FLT_ARG_CNT,%r13         /* are we out of float argument         */
222         je      L_register_copy           /* register? yes, next loop             */
223
224         lea     jumptable_float,%rbp
225         mov     0(%rbp,%r13,8),%rbx
226         inc     %r13                      /* float argument counter + 1           */
227         jmp     *%rbx
228         
229 L_register_copy_done:
230         mov     %r15,%rbp                 /* calculate remaining arguments        */
231         sub     %r12,%rbp                 /* - integer arguments in registers     */
232         sub     %r13,%rbp                 /* - float arguments in registers       */
233         jle     L_copy_done               /* are all assigned to registers?       */
234
235         and     $0xfffffffffffffffe,%rbp  /* keep stack 16-byte aligned           */
236         shl     $3,%rbp                   /* calculate stack size                 */
237         sub     %rbp,sp                 /* stack frame for arguments            */
238         mov     sp,%rbx                 /* use %rbx as temp sp                  */
239
240         sub     $sizejniblock,%r14        /* initialize pointer (smaller code)    */
241         add     $1,%r15                   /* initialize argument count            */
242                 
243 L_stack_copy_loop:
244         add     $sizejniblock,%r14        /* goto next argument block             */
245         dec     %r15                      /* are there any arguments left?        */
246         jz      L_copy_done               /* no test needed after dec             */
247
248         andb    $0x02,offjniitemtype(%r14) /* is this a float/double type?        */
249         jnz     L_stack_handle_float
250         dec     %r12                      /* arguments assigned to registers      */
251         jge     L_stack_copy_loop
252         jmp     L_stack_copy
253
254 L_stack_handle_float:
255         dec     %r13                      /* arguments assigned to registers      */
256         jge     L_stack_copy_loop
257
258 L_stack_copy:
259     mov     offjniitem(%r14),itmp3    /* copy s8 argument onto stack          */
260     mov     itmp3,0(%rbx)
261     add     $8,%rbx                   /* increase sp to next argument         */
262         jmp     L_stack_copy_loop
263
264 L_copy_done:
265         lea     asm_call_jit_compiler,itmp3 /* %rax still contains method pointer */
266         call    *itmp3                    /* call JIT compiler                    */
267
268         add     bp,sp                     /* remove argument stack frame if any   */
269
270 L_asm_calljavafunction2_return:
271         mov     0*8(sp),%rbx                /* restore callee saved registers     */
272         mov     1*8(sp),s0
273         mov     2*8(sp),s1
274         mov     3*8(sp),s2
275         mov     4*8(sp),s3
276         mov     5*8(sp),s4
277         add     $(7*8),sp                   /* free stack space                   */
278         ret
279                 
280 calljava_xhandler2:
281         mov     xptr,a0                     /* pass exception pointer             */
282         call    builtin_throw_exception
283         xor     v0,v0                       /* return NULL                        */
284         jmp     L_asm_calljavafunction2_return
285
286
287 jumptable_integer:
288         .quad   handle_a0
289         .quad   handle_a1
290         .quad   handle_a2
291         .quad   handle_a3
292         .quad   handle_a4
293         .quad   handle_a5
294
295 handle_a0:
296         mov     offjniitem(itmp2),a0
297         jmp     L_register_copy
298 handle_a1:
299         mov     offjniitem(itmp2),a1
300         jmp     L_register_copy
301 handle_a2:
302         mov     offjniitem(itmp2),a2
303         jmp     L_register_copy
304 handle_a3:
305         mov     offjniitem(itmp2),a3
306         jmp     L_register_copy
307 handle_a4:
308         mov     offjniitem(itmp2),a4
309         jmp     L_register_copy
310 handle_a5:
311         mov     offjniitem(itmp2),a5
312         jmp     L_register_copy
313
314
315 jumptable_float:
316         .quad   handle_fa0
317         .quad   handle_fa1
318         .quad   handle_fa2
319         .quad   handle_fa3
320         .quad   handle_fa4
321         .quad   handle_fa5
322         .quad   handle_fa6
323         .quad   handle_fa7
324
325 handle_fa0:
326         movq    offjniitem(itmp2),fa0
327         jmp     L_register_copy
328 handle_fa1:
329         movq    offjniitem(itmp2),fa1
330         jmp     L_register_copy
331 handle_fa2:
332         movq    offjniitem(itmp2),fa2
333         jmp     L_register_copy
334 handle_fa3:
335         movq    offjniitem(itmp2),fa3
336         jmp     L_register_copy
337 handle_fa4:
338         movq    offjniitem(itmp2),fa4
339         jmp     L_register_copy
340 handle_fa5:
341         movq    offjniitem(itmp2),fa5
342         jmp     L_register_copy
343 handle_fa6:
344         movq    offjniitem(itmp2),fa6
345         jmp     L_register_copy
346 handle_fa7:
347         movq    offjniitem(itmp2),fa7
348         jmp     L_register_copy
349
350
351 /****************** function asm_call_jit_compiler *****************************
352 *                                                                              *
353 *   invokes the compiler for untranslated JavaVM methods.                      *
354 *                                                                              *
355 *   Register R0 contains a pointer to the method info structure (prepared      *
356 *   by createcompilerstub). Using the return address in R26 and the            *
357 *   offset in the LDA instruction or using the value in methodptr R28 the      *
358 *   patching address for storing the method address can be computed:           *
359 *                                                                              *
360 *   method address was either loaded using                                     *
361 *                                                                              *
362 *   i386_mov_imm_reg(a, REG_ITMP2)                ; invokestatic/special       *
363 *   i386_call_reg(REG_ITMP2)                                                   *
364 *                                                                              *
365 *   or                                                                         *
366 *                                                                              *
367 *   i386_mov_membase_reg(REG_SP, 0, REG_ITMP2)    ; invokevirtual/interface    *
368 *   i386_mov_membase_reg(REG_ITMP2, OFFSET(, vftbl), REG_ITMP3)                *
369 *   i386_mov_membase_reg(REG_ITMP3, OFFSET(vftbl, table[0]) + \                *
370 *       sizeof(methodptr) * m->vftblindex, REG_ITMP1)                          *
371 *   i386_call_reg(REG_ITMP1)                                                   *
372 *                                                                              *
373 *   in the static case the method pointer can be computed using the            *
374 *   return address and the lda function following the jmp instruction          *
375 *                                                                              *
376 *******************************************************************************/
377
378 asm_call_jit_compiler:
379                                             /* keep stack 16-byte aligned         */
380         sub     $((3+ARG_CNT)*8+sizestackframeinfo),sp
381
382         mov     t0,0*8(sp)                  /* save register                      */
383
384         mov     (3+ARG_CNT)*8+sizestackframeinfo(sp),itmp3 /* get return address  */
385         mov     -1(itmp3),%bl               /* get function code                  */
386         cmp     $0xd2,%bl                   /* called with `call *REG_ITMP2'?     */
387         jne     L_not_static_special
388
389         sub     $11,itmp3                   /* calculate address of immediate     */
390         jmp     L_call_jit_compile
391                 
392 L_not_static_special:
393         cmp     $0xd0,%bl                   /* called with `call *REG_ITMP1'      */
394         jne     L_not_virtual_interface
395                 
396         sub     $7,itmp3                    /* calculate address of offset        */
397         mov     (itmp3),itmp3l              /* get offset (32-bit)                */
398         add     itmp2,itmp3                 /* add base address to get method addr*/
399         jmp     L_call_jit_compile
400
401 L_not_virtual_interface:                /* a call from asm_calljavamethod     */
402         xor     itmp3,itmp3
403                 
404 L_call_jit_compile:
405         mov     0*8(sp),t0                  /* restore register                   */
406         mov     itmp3,0*8(sp)               /* save address for method pointer    */
407         mov     itmp1,1*8(sp)               /* save method pointer                */
408
409         SAVE_ARGUMENT_REGISTERS(3)
410
411         mov     sp,a0                       /* create stackframe info             */
412         add     $((3+ARG_CNT)*8),a0         /* pass sfi                           */
413         xor     a1,a1                       /* if pv is NULL, use findmethod      */
414         mov     sp,a2                       /* pass java sp                       */
415         add     $((1+3+ARG_CNT)*8+sizestackframeinfo),a2
416                                             /* pass ra to java function           */
417         mov     ((3+ARG_CNT)*8+sizestackframeinfo)(sp),a3
418         mov     a3,a4                       /* xpc is equal to ra                 */
419         call    stacktrace_create_extern_stackframeinfo
420
421         mov     1*8(sp),a0                  /* pass method pointer                */
422         call    jit_compile
423         mov     v0,1*8(sp)                  /* save return value                  */
424
425         mov     sp,a0                       /* remove stackframe info             */
426         add     $((3+ARG_CNT)*8),a0         /* pass sfi                           */
427         call    stacktrace_remove_stackframeinfo
428
429         mov     0*8(sp),itmp3               /* restore address for method pointer */
430         mov     1*8(sp),v0                  /* restore return value               */
431
432         RESTORE_ARGUMENT_REGISTERS(3)
433
434         add     $((3+ARG_CNT)*8+sizestackframeinfo),sp /* remove stack frame      */
435
436         test    v0,v0                       /* check for exception                */
437         je      L_asm_call_jit_compiler_exception
438
439         test    itmp3,itmp3                 /* is address == 0 (asm_calljavamethod*/
440         je      L_call_method
441
442         mov     v0,(itmp3)                  /* and now save the new pointer       */
443
444 L_call_method:
445         jmp     *v0                         /* ...and now call the new method     */
446
447 L_asm_call_jit_compiler_exception:
448 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
449         call    builtin_asm_get_exceptionptrptr
450         mov     v0,itmp2                    /* v0 == xptr                         */
451 #else
452         lea     _no_threads_exceptionptr,itmp2
453 #endif
454         mov     (itmp2),xptr                /* get the exception pointer          */
455         movl    $0,(itmp2)                  /* clear exception pointer            */
456
457         pop     xpc                         /* delete return address              */
458         sub     $5,xpc                      /* faulting address is ra - 5         */
459         jmp     asm_handle_exception
460
461
462 /* asm_handle_exception ********************************************************
463 *                                                                              *
464 *   This function handles an exception. It does not use the usual calling      *
465 *   conventions. The exception pointer is passed in REG_ITMP1 and the          *
466 *   pc from the exception raising position is passed in REG_ITMP2. It searches *
467 *   the local exception table for a handler. If no one is found, it unwinds    *
468 *   stacks and continues searching the callers.                                *
469 *                                                                              *
470 *******************************************************************************/
471
472 asm_handle_nat_exception:
473         add     $8,sp                       /* clear return address of native stub*/
474                 
475 asm_handle_exception:
476         sub     $((ARG_CNT+TMP_CNT)*8),sp   /* create maybe-leaf stackframe       */
477
478         SAVE_ARGUMENT_REGISTERS(0)          /* we save arg and temp registers in  */
479         SAVE_TEMPORARY_REGISTERS(ARG_CNT)   /* case this is a leaf method         */
480
481         mov     $((ARG_CNT+TMP_CNT)*8),a3   /* prepare a3 for handle_exception    */
482         mov     $1,t0                       /* set maybe-leaf flag                */
483
484 L_asm_handle_exception_stack_loop:
485         sub     $(6*8),sp
486         mov     xptr,0*8(sp)                /* save exception pointer             */
487         mov     xpc,1*8(sp)                 /* save exception pc                  */
488         add     sp,a3                       /* calculate Java sp into a3...       */
489         add     $(6*8),a3
490         mov     a3,3*8(sp)                  /* ...and save it                     */
491         mov     t0,4*8(sp)                  /* save maybe-leaf flag               */
492
493         mov     xpc,a0                      /* exception pc                       */
494         call    codegen_findmethod
495         mov     v0,2*8(sp)                  /* save data segment pointer          */
496         
497         mov     0*8(sp),a0                  /* pass exception pointer             */
498         mov     1*8(sp),a1                  /* pass exception pc                  */
499         mov     v0,a2                       /* pass data segment pointer          */
500         mov     3*8(sp),a3                  /* pass Java stack pointer            */
501         call    exceptions_handle_exception
502
503         test    v0,v0
504         jz      L_asm_handle_exception_not_catched
505
506         mov     v0,xpc                      /* move handlerpc into xpc            */
507         mov     0*8(sp),xptr                /* restore exception pointer          */
508         mov     4*8(sp),t0                  /* get maybe-leaf flag                */
509         add     $(6*8),sp                   /* free stack frame                   */
510
511         test    t0,t0                       /* test for maybe-leaf flag           */
512         jz      L_asm_handle_exception_no_leaf
513
514         RESTORE_ARGUMENT_REGISTERS(0)       /* if this is a leaf method, we have  */
515         RESTORE_TEMPORARY_REGISTERS(ARG_CNT)/* to restore arg and temp registers  */
516
517         add     $((ARG_CNT+TMP_CNT)*8),sp   /* remove maybe-leaf stackframe       */
518
519 L_asm_handle_exception_no_leaf:
520         jmp     *xpc                        /* jump to the handler                */
521
522 L_asm_handle_exception_not_catched:
523         mov     0*8(sp),xptr                /* restore exception pointer          */
524         mov     2*8(sp),itmp3               /* restore data segment pointer       */
525         mov     4*8(sp),t0                  /* get maybe-leaf flag                */
526         add     $(6*8),sp
527
528         test    t0,t0
529         jz      L_asm_handle_exception_no_leaf_stack
530
531         add     $((ARG_CNT+TMP_CNT)*8),sp   /* remove maybe-leaf stackframe       */
532         xor     t0,t0                       /* clear the isleaf flags             */
533
534 L_asm_handle_exception_no_leaf_stack:
535         mov     FrameSize(itmp3),itmp2l     /* get frame size                     */
536         add     sp,itmp2                    /* pointer to save area               */
537         
538         mov     IntSave(itmp3),a0l          /* a0l = saved int register count     */
539         test    a0l,a0l
540         je      noint
541         
542         cmp     $1,a0l
543         je      int1
544         cmp     $2,a0l
545         je      int2
546         cmp     $3,a0l
547         je      int3
548         cmp     $4,a0l
549         je      int4
550         
551         mov     -5*8(itmp2),s0
552 int4:   
553         mov     -4*8(itmp2),s1
554 int3:   
555         mov     -3*8(itmp2),s2
556 int2:   
557         mov     -2*8(itmp2),s3
558 int1:   
559         mov     -1*8(itmp2),s4
560
561         shl     $3,a0l                      /* multiply by 8 bytes                */
562         sub     a0,itmp2
563                 
564 noint:
565 #if 0
566         mov     FltSave(itmp3),a0l          /* a0l = saved flt register count     */
567         test    a0l,a0l
568         je      noflt
569         
570         cmpl    $1,a0l
571         je      flt1
572         cmpl    $2,a0l
573         je      flt2
574         cmpl    $3,a0l
575         je      flt3
576         cmpl    $4,a0l
577         je      flt4
578
579         movq    -5*8(itmp2),%xmm11
580 flt4:   
581         movq    -4*8(itmp2),%xmm12
582 flt3:   
583         movq    -3*8(itmp2),%xmm13
584 flt2:   
585         movq    -2*8(itmp2),%xmm14
586 flt1:   
587         movq    -1*8(itmp2),%xmm15
588                 
589 noflt:
590 #endif
591         mov     FrameSize(itmp3),itmp2l     /* get frame size                     */
592         add     itmp2,sp                    /* unwind stack                       */
593
594                                             /* exception pointer is still set     */
595         pop     xpc                         /* the new xpc is return address      */
596         sub     $3,xpc                      /* subtract 3 bytes for call          */
597
598         xor     a3,a3                       /* prepare a3 for handle_exception    */
599         
600         jmp             L_asm_handle_exception_stack_loop
601
602
603 /* asm_wrapper_patcher *********************************************************
604
605    XXX
606
607    Stack layout:
608      40   return address
609      32   pointer to virtual java_objectheader
610      24   machine code (which is patched back later)
611      16   unresolved class/method/field reference
612       8   data segment displacement from load instructions
613       0   pointer to patcher function
614      -8   bp
615
616 *******************************************************************************/
617
618 asm_wrapper_patcher:
619         push    bp                          /* save base pointer                  */
620         mov     sp,bp                       /* move actual sp to bp               */
621         sub     $((3+ARG_CNT+TMP_CNT)*8+sizestackframeinfo),sp
622         and     $0xfffffffffffffff0,sp      /* align sp to 16-byte (this is for   */
623                                             /* leaf functions)                    */
624
625         SAVE_ARGUMENT_REGISTERS(3)
626         SAVE_TEMPORARY_REGISTERS(3+ARG_CNT)
627
628         mov     itmp1,0*8(sp)               /* save itmp1 and itmp2               */
629         mov     itmp2,1*8(sp)               /* can be used by some instructions   */
630
631         mov     sp,a0                       /* create stackframe info             */
632         add     $((3+ARG_CNT+TMP_CNT)*8),a0
633         xor     a1,a1                       /* if pv is NULL, use findmethod      */
634         mov     bp,a2                       /* pass java sp                       */
635         add     $((6+1)*8),a2
636         mov     ((5+1)*8)(bp),a3            /* pass ra to java function           */
637         mov     a3,a4                       /* xpc is equal to ra                 */
638         call    stacktrace_create_extern_stackframeinfo
639
640         mov     bp,a0                       /* pass stack pointer                 */
641         add     $((1+1)*8),a0               /* skip function pointer              */
642         mov     1*8(bp),itmp3               /* get function pointer               */
643         call    *itmp3                      /* call the patcher function          */
644         mov     v0,2*8(sp)                  /* save return value                  */
645
646         mov     sp,a0                       /* remove stackframe info             */
647         add     $((3+ARG_CNT+TMP_CNT)*8),a0
648         call    stacktrace_remove_stackframeinfo
649
650         RESTORE_ARGUMENT_REGISTERS(3)
651         RESTORE_TEMPORARY_REGISTERS(3+ARG_CNT)
652
653         mov     0*8(sp),itmp1               /* restore itmp1 and itmp2            */
654         mov     1*8(sp),itmp2               /* can be used by some instructions   */
655         mov     2*8(sp),itmp3               /* restore return value               */
656
657         mov     bp,sp                       /* restore original sp                */
658         pop     bp                          /* restore bp                         */
659         add     $(5*8),sp                   /* remove patcher stackframe, keep ra */
660
661         test    itmp3,itmp3                 /* exception thrown?                  */
662         jz      L_asm_wrapper_patcher_exception
663         ret                                 /* call new patched code              */
664
665 L_asm_wrapper_patcher_exception:
666 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
667         call    builtin_asm_get_exceptionptrptr
668         mov     v0,itmp2                    /* v0 == xptr                         */
669 #else
670         lea     _no_threads_exceptionptr,itmp2
671 #endif
672         mov     (itmp2),xptr                /* get the exception pointer          */
673         movl    $0,(itmp2)                  /* clear exception pointer            */
674
675         pop     xpc                         /* get and remove return address      */
676         jmp     asm_handle_exception
677
678
679 /* asm_builtin_x2x *************************************************************
680 *                                                                              *
681 *   Wrapper functions for float to int corner cases                            *
682 *                                                                              *
683 *******************************************************************************/
684
685 asm_builtin_f2i:
686         sub     $(ARG_CNT*8),sp
687         
688         SAVE_ARGUMENT_REGISTERS(0)
689         
690         movq    ftmp1,fa0
691         call    builtin_f2i
692         
693         RESTORE_ARGUMENT_REGISTERS(0)
694         
695         add     $(ARG_CNT*8),sp
696         ret
697
698
699 asm_builtin_f2l:
700         sub     $(ARG_CNT*8),sp
701         
702         SAVE_ARGUMENT_REGISTERS(0)
703         
704         movq    ftmp1,fa0
705         call    builtin_f2l
706         
707         RESTORE_ARGUMENT_REGISTERS(0)
708         
709         add     $(ARG_CNT*8),sp
710         ret
711
712
713 asm_builtin_d2i:
714         sub     $(ARG_CNT*8),sp
715         
716         SAVE_ARGUMENT_REGISTERS(0)
717         
718         movq    ftmp1,fa0
719         call    builtin_d2i
720         
721         RESTORE_ARGUMENT_REGISTERS(0)
722         
723         add     $(ARG_CNT*8),sp
724         ret
725
726
727 asm_builtin_d2l:
728         sub     $(ARG_CNT*8),sp
729         
730         SAVE_ARGUMENT_REGISTERS(0)
731         
732         movq    ftmp1,fa0
733         call    builtin_d2l
734         
735         RESTORE_ARGUMENT_REGISTERS(0)
736         
737         add     $(ARG_CNT*8),sp
738         ret
739
740
741 /******************* function asm_initialize_thread_stack **********************
742 *                                                                              *
743 * initialized a thread stack                                                   *
744 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
745 *                                                                              *
746 *******************************************************************************/
747
748 asm_initialize_thread_stack:
749         sub     $(7*8),%rsi
750
751         xor     %r10,%r10
752         mov     %r10,0*8(%rsi)
753         mov     %r10,1*8(%rsi)
754         mov     %r10,2*8(%rsi)
755         mov     %r10,3*8(%rsi)
756         mov     %r10,4*8(%rsi)
757         mov     %r10,5*8(%rsi)
758
759         mov     %rdi,6*8(%rsi)          /* save (u1*) (func)                  */
760         mov     %rsi,%rax               /* return restorepoint in %rax        */
761         ret
762
763
764 /******************* function asm_perform_threadswitch *************************
765 *                                                                              *
766 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
767 *                                                                              *
768 *   performs a threadswitch                                                    *
769 *                                                                              *
770 *******************************************************************************/
771
772 asm_perform_threadswitch:
773         sub     $(7*8),%rsp             /* allocate stack frame               */
774
775         mov     %rbx,0*8(%rsp)
776         mov     %rbp,1*8(%rsp)
777         mov     %r12,2*8(%rsp)
778         mov     %r13,3*8(%rsp)
779         mov     %r14,4*8(%rsp)
780         mov     %r15,5*8(%rsp)
781
782         mov     7*8(%rsp),%rax                  /* save current return address        */
783         mov     %rax,6*8(%rsp)
784
785         mov     %rsp,(%rdi)                     /* first argument **from              */
786         mov     %rsp,(%rdx)                     /* third argument **stackTop          */
787
788         mov     (%rsi),%rsp                     /* load new stack pointer             */
789
790         mov     0*8(%rsp),%rbx
791         mov     1*8(%rsp),%rbp
792         mov     2*8(%rsp),%r12
793         mov     3*8(%rsp),%r13
794         mov     4*8(%rsp),%r14
795         mov     5*8(%rsp),%r15
796
797         mov     6*8(%rsp),%rax          /* restore return address             */
798         add     $(7*8),%rsp             /* free stack frame                   */
799         mov     %rax,(%rsp)
800         ret
801                 
802
803 /********************* function asm_switchstackandcall *************************
804 *                                                                              *
805 *  int asm_switchstackandcall (void *stack, void *func, void **stacktopsave,   *
806 *                                      void *p);                                       *
807 *                                                                              *
808 *   Switches to a new stack, calls a function and switches back.               *
809 *       a0 (%rdi)     new stack pointer                                        *
810 *       a1 (%rsi)     function pointer                                         *
811 *               a2 (%rdx)     pointer to variable where stack top should be stored     *
812 *       a3 (%rcx)     pointer to user data, is passed to the function          *
813 *                                                                              *
814 *******************************************************************************/
815
816 asm_switchstackandcall:
817         sub     $(1*8),%rsp             /* keep stack 16-byte aligned         */
818         sub     $16,%rdi                                /* allocate new stack                 */
819
820         mov     8(%rsp),%rax                    /* save return address on new stack   */
821         mov     %rax,(%rdi)
822         mov     %rsp,8(%rdi)                    /* save old stack pointer on new stack*/
823         mov     %rsp,(%rdx)                             /* save old stack pointer to variable */
824
825         mov     %rdi,%rsp                               /* switch to new stack                */
826
827         mov     %rcx,%rdi                       /* pass pointer                       */
828         call    *%rsi                                   /* and call function                  */
829
830         mov     (%rsp),%r10                             /* load return address                */
831         mov     8(%rsp),%rsp                    /* switch to old stack                */
832         add     $(1*8),%rsp             /* free stack space                   */
833         mov     %r10,(%rsp)             /* write return adress                */
834         ret
835
836
837 asm_getclassvalues_atomic:
838 _crit_restart:
839 _crit_begin:
840         movl    offbaseval(a0),itmp1l
841         movl    offdiffval(a0),itmp2l
842         movl    offbaseval(a1),itmp3l
843 _crit_end:
844         movl    itmp1l,offcast_super_baseval(a2)
845         movl    itmp2l,offcast_super_diffval(a2)
846         movl    itmp3l,offcast_sub_baseval(a2)
847         ret
848
849         .data
850                 
851 asm_criticalsections:
852 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
853         .quad   _crit_begin
854         .quad   _crit_end
855         .quad   _crit_restart
856 #endif
857         .quad 0
858
859
860 /*
861  * These are local overrides for various environment variables in Emacs.
862  * Please do not remove this and leave it at the end of the file, where
863  * Emacs will automagically detect them.
864  * ---------------------------------------------------------------------
865  * Local variables:
866  * mode: asm
867  * indent-tabs-mode: t
868  * c-basic-offset: 4
869  * tab-width: 4
870  * End:
871  */