* vm/jit/abi.h: Added.
[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 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:
32
33    $Id: asmpart.S 3910 2005-12-08 14:32:53Z 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,a4                       /* 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     a4,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),a4                  /* get maybe-leaf flag                */
509         add     $(6*8),sp                   /* free stack frame                   */
510
511         test    a4,a4                       /* 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),a4                  /* get maybe-leaf flag                */
526         add     $(6*8),sp
527
528         test    a4,a4
529         jz      L_asm_handle_exception_no_leaf_stack
530
531         add     $((ARG_CNT+TMP_CNT)*8),sp   /* remove maybe-leaf stackframe       */
532         xor     a4,a4                       /* clear the isleaf flags             */
533
534 L_asm_handle_exception_no_leaf_stack:
535         mov     FrameSize(itmp3),itmp2l     /* get frame size                     */
536         add     itmp2,sp                    /* unwind stack                       */
537         mov     sp,itmp2                    /* pointer to save area               */
538         
539         mov     IntSave(itmp3),t0l          /* t0l = saved int register count     */
540         test    t0l,t0l
541         je      noint
542         
543         cmp     $1,t0l
544         je      int1
545         cmp     $2,t0l
546         je      int2
547         cmp     $3,t0l
548         je      int3
549         cmp     $4,t0l
550         je      int4
551         
552         mov     -40(itmp2),%rbp
553 int4:   
554         mov     -32(itmp2),%r12
555 int3:   
556         mov     -24(itmp2),%r13
557 int2:   
558         mov     -16(itmp2),%r14
559 int1:   
560         mov     -8(itmp2),%r15
561
562         shl     $3,t0l                      /* multiply by 8 bytes                */
563         sub     t0,itmp2
564                 
565 noint:
566         mov     FltSave(itmp3),t0l          /* t0l = saved flt register count     */
567         test    t0l,t0l
568         je      noflt
569         
570         cmpl    $1,t0l
571         je      flt1
572         cmpl    $2,t0l
573         je      flt2
574         cmpl    $3,t0l
575         je      flt3
576         cmpl    $4,t0l
577         je      flt4
578
579         movq    -40(itmp2),%xmm11
580 flt4:   
581         movq    -32(itmp2),%xmm12
582 flt3:   
583         movq    -24(itmp2),%xmm13
584 flt2:   
585         movq    -16(itmp2),%xmm14
586 flt1:   
587         movq    -8(itmp2),%xmm15
588                 
589 noflt:                                  
590                                             /* exception pointer is still set     */
591         pop     xpc                         /* the new xpc is return address      */
592         sub     $3,xpc                      /* subtract 3 bytes for call          */
593
594         xor     a3,a3                       /* prepare a3 for handle_exception    */
595         
596         jmp             L_asm_handle_exception_stack_loop
597
598
599 /* asm_wrapper_patcher *********************************************************
600
601    XXX
602
603    Stack layout:
604      40   return address
605      32   pointer to virtual java_objectheader
606      24   machine code (which is patched back later)
607      16   unresolved class/method/field reference
608       8   data segment displacement from load instructions
609       0   pointer to patcher function
610      -8   bp
611
612 *******************************************************************************/
613
614 asm_wrapper_patcher:
615         push    bp                          /* save base pointer                  */
616         mov     sp,bp                       /* move actual sp to bp               */
617         sub     $((3+ARG_CNT+TMP_CNT)*8+sizestackframeinfo),sp
618         and     $0xfffffffffffffff0,sp      /* align sp to 16-byte (this is for   */
619                                             /* leaf functions)                    */
620
621         SAVE_ARGUMENT_REGISTERS(3)
622         SAVE_TEMPORARY_REGISTERS(3+ARG_CNT)
623
624         mov     itmp1,0*8(sp)               /* save itmp1 and itmp2               */
625         mov     itmp2,1*8(sp)               /* can be used by some instructions   */
626
627         mov     sp,a0                       /* create stackframe info             */
628         add     $((3+ARG_CNT+TMP_CNT)*8),a0
629         xor     a1,a1                       /* if pv is NULL, use findmethod      */
630         mov     bp,a2                       /* pass java sp                       */
631         add     $((6+1)*8),a2
632         mov     ((5+1)*8)(bp),a3            /* pass ra to java function           */
633         mov     a3,a4                       /* xpc is equal to ra                 */
634         call    stacktrace_create_extern_stackframeinfo
635
636         mov     bp,a0                       /* pass stack pointer                 */
637         add     $((1+1)*8),a0               /* skip function pointer              */
638         mov     1*8(bp),itmp3               /* get function pointer               */
639         call    *itmp3                      /* call the patcher function          */
640         mov     v0,2*8(sp)                  /* save return value                  */
641
642         mov     sp,a0                       /* remove stackframe info             */
643         add     $((3+ARG_CNT+TMP_CNT)*8),a0
644         call    stacktrace_remove_stackframeinfo
645
646         RESTORE_ARGUMENT_REGISTERS(3)
647         RESTORE_TEMPORARY_REGISTERS(3+ARG_CNT)
648
649         mov     0*8(sp),itmp1               /* restore itmp1 and itmp2            */
650         mov     1*8(sp),itmp2               /* can be used by some instructions   */
651         mov     2*8(sp),itmp3               /* restore return value               */
652
653         mov     bp,sp                       /* restore original sp                */
654         pop     bp                          /* restore bp                         */
655         add     $(5*8),sp                   /* remove patcher stackframe, keep ra */
656
657         test    itmp3,itmp3                 /* exception thrown?                  */
658         jz      L_asm_wrapper_patcher_exception
659         ret                                 /* call new patched code              */
660
661 L_asm_wrapper_patcher_exception:
662 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
663         call    builtin_asm_get_exceptionptrptr
664         mov     v0,itmp2                    /* v0 == xptr                         */
665 #else
666         lea     _no_threads_exceptionptr,itmp2
667 #endif
668         mov     (itmp2),xptr                /* get the exception pointer          */
669         movl    $0,(itmp2)                  /* clear exception pointer            */
670
671         pop     xpc                         /* get and remove return address      */
672         jmp     asm_handle_exception
673
674
675 /* asm_builtin_x2x *************************************************************
676 *                                                                              *
677 *   Wrapper functions for float to int corner cases                            *
678 *                                                                              *
679 *******************************************************************************/
680
681 asm_builtin_f2i:
682         sub     $(ARG_CNT*8),sp
683         
684         SAVE_ARGUMENT_REGISTERS(0)
685         
686         movq    ftmp1,fa0
687         call    builtin_f2i
688         
689         RESTORE_ARGUMENT_REGISTERS(0)
690         
691         add     $(ARG_CNT*8),sp
692         ret
693
694
695 asm_builtin_f2l:
696         sub     $(ARG_CNT*8),sp
697         
698         SAVE_ARGUMENT_REGISTERS(0)
699         
700         movq    ftmp1,fa0
701         call    builtin_f2l
702         
703         RESTORE_ARGUMENT_REGISTERS(0)
704         
705         add     $(ARG_CNT*8),sp
706         ret
707
708
709 asm_builtin_d2i:
710         sub     $(ARG_CNT*8),sp
711         
712         SAVE_ARGUMENT_REGISTERS(0)
713         
714         movq    ftmp1,fa0
715         call    builtin_d2i
716         
717         RESTORE_ARGUMENT_REGISTERS(0)
718         
719         add     $(ARG_CNT*8),sp
720         ret
721
722
723 asm_builtin_d2l:
724         sub     $(ARG_CNT*8),sp
725         
726         SAVE_ARGUMENT_REGISTERS(0)
727         
728         movq    ftmp1,fa0
729         call    builtin_d2l
730         
731         RESTORE_ARGUMENT_REGISTERS(0)
732         
733         add     $(ARG_CNT*8),sp
734         ret
735
736
737 /******************* function asm_initialize_thread_stack **********************
738 *                                                                              *
739 * initialized a thread stack                                                   *
740 * (to)->restorePoint = asm_initialize_thread_stack((u1*)(func), (to)->stackEnd)*
741 *                                                                              *
742 *******************************************************************************/
743
744 asm_initialize_thread_stack:
745         sub     $(7*8),%rsi
746
747         xor     %r10,%r10
748         mov     %r10,0*8(%rsi)
749         mov     %r10,1*8(%rsi)
750         mov     %r10,2*8(%rsi)
751         mov     %r10,3*8(%rsi)
752         mov     %r10,4*8(%rsi)
753         mov     %r10,5*8(%rsi)
754
755         mov     %rdi,6*8(%rsi)          /* save (u1*) (func)                  */
756         mov     %rsi,%rax               /* return restorepoint in %rax        */
757         ret
758
759
760 /******************* function asm_perform_threadswitch *************************
761 *                                                                              *
762 *   void asm_perform_threadswitch (u1 **from, u1 **to, u1 **stackTop);         *
763 *                                                                              *
764 *   performs a threadswitch                                                    *
765 *                                                                              *
766 *******************************************************************************/
767
768 asm_perform_threadswitch:
769         sub     $(7*8),%rsp             /* allocate stack frame               */
770
771         mov     %rbx,0*8(%rsp)
772         mov     %rbp,1*8(%rsp)
773         mov     %r12,2*8(%rsp)
774         mov     %r13,3*8(%rsp)
775         mov     %r14,4*8(%rsp)
776         mov     %r15,5*8(%rsp)
777
778         mov     7*8(%rsp),%rax                  /* save current return address        */
779         mov     %rax,6*8(%rsp)
780
781         mov     %rsp,(%rdi)                     /* first argument **from              */
782         mov     %rsp,(%rdx)                     /* third argument **stackTop          */
783
784         mov     (%rsi),%rsp                     /* load new stack pointer             */
785
786         mov     0*8(%rsp),%rbx
787         mov     1*8(%rsp),%rbp
788         mov     2*8(%rsp),%r12
789         mov     3*8(%rsp),%r13
790         mov     4*8(%rsp),%r14
791         mov     5*8(%rsp),%r15
792
793         mov     6*8(%rsp),%rax          /* restore return address             */
794         add     $(7*8),%rsp             /* free stack frame                   */
795         mov     %rax,(%rsp)
796         ret
797                 
798
799 /********************* function asm_switchstackandcall *************************
800 *                                                                              *
801 *  int asm_switchstackandcall (void *stack, void *func, void **stacktopsave,   *
802 *                                      void *p);                                       *
803 *                                                                              *
804 *   Switches to a new stack, calls a function and switches back.               *
805 *       a0 (%rdi)     new stack pointer                                        *
806 *       a1 (%rsi)     function pointer                                         *
807 *               a2 (%rdx)     pointer to variable where stack top should be stored     *
808 *       a3 (%rcx)     pointer to user data, is passed to the function          *
809 *                                                                              *
810 *******************************************************************************/
811
812 asm_switchstackandcall:
813         sub     $(1*8),%rsp             /* keep stack 16-byte aligned         */
814         sub     $16,%rdi                                /* allocate new stack                 */
815
816         mov     8(%rsp),%rax                    /* save return address on new stack   */
817         mov     %rax,(%rdi)
818         mov     %rsp,8(%rdi)                    /* save old stack pointer on new stack*/
819         mov     %rsp,(%rdx)                             /* save old stack pointer to variable */
820
821         mov     %rdi,%rsp                               /* switch to new stack                */
822
823         mov     %rcx,%rdi                       /* pass pointer                       */
824         call    *%rsi                                   /* and call function                  */
825
826         mov     (%rsp),%r10                             /* load return address                */
827         mov     8(%rsp),%rsp                    /* switch to old stack                */
828         add     $(1*8),%rsp             /* free stack space                   */
829         mov     %r10,(%rsp)             /* write return adress                */
830         ret
831
832
833 asm_getclassvalues_atomic:
834 _crit_restart:
835 _crit_begin:
836         movl    offbaseval(a0),itmp1l
837         movl    offdiffval(a0),itmp2l
838         movl    offbaseval(a1),itmp3l
839 _crit_end:
840         movl    itmp1l,offcast_super_baseval(a2)
841         movl    itmp2l,offcast_super_diffval(a2)
842         movl    itmp3l,offcast_sub_baseval(a2)
843         ret
844
845         .data
846                 
847 asm_criticalsections:
848 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
849         .quad   _crit_begin
850         .quad   _crit_end
851         .quad   _crit_restart
852 #endif
853         .quad 0
854
855
856 /*
857  * These are local overrides for various environment variables in Emacs.
858  * Please do not remove this and leave it at the end of the file, where
859  * Emacs will automagically detect them.
860  * ---------------------------------------------------------------------
861  * Local variables:
862  * mode: asm
863  * indent-tabs-mode: t
864  * c-basic-offset: 4
865  * tab-width: 4
866  * End:
867  */