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