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