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