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